enabled ScanResponse for Advertising in BLE server
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / android / caleserver.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 <jni.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <android/log.h>
25 #include <unistd.h>
26 #include "caleserver.h"
27 #include "caleutils.h"
28 #include "caleinterface.h"
29 #include "caadapterutils.h"
30
31 #include "logger.h"
32 #include "oic_malloc.h"
33 #include "cathreadpool.h"
34 #include "camutex.h"
35 #include "uarraylist.h"
36 #include "org_iotivity_ca_CaLeServerInterface.h"
37
38 #define TAG PCF("OIC_CA_LE_SERVER")
39
40 #define WAIT_TIME_WRITE_CHARACTERISTIC 10000000
41
42 static JavaVM *g_jvm = NULL;
43 static jobject g_context = NULL;
44 static jobject g_bluetoothGattServer = NULL;
45 static jobject g_bluetoothGattServerCallback = NULL;
46 static jobject g_leAdvertiseCallback = NULL;
47 static jobject g_bluetoothManager = NULL;
48
49 static CAPacketReceiveCallback g_packetReceiveCallback = NULL;
50 static CABLEErrorHandleCallback g_serverErrorCallback;
51
52 static u_arraylist_t *g_connectedDeviceList = NULL;
53
54 static bool g_isStartServer = false;
55 static bool g_isInitializedServer = false;
56
57 static jbyteArray g_sendBuffer = NULL;
58 static jobject g_obj_bluetoothDevice = NULL;
59
60 static CABLEDataReceivedCallback g_CABLEServerDataReceivedCallback = NULL;
61 static ca_mutex g_bleReqRespCbMutex = NULL;
62 static ca_mutex g_bleClientBDAddressMutex = NULL;
63 static ca_mutex g_connectedDeviceListMutex = NULL;
64
65 static ca_mutex g_threadSendMutex = NULL;
66 static ca_mutex g_threadSendNotifyMutex = NULL;
67 static ca_cond g_threadSendNotifyCond = NULL;
68 static bool g_isSignalSetFlag = false;
69
70 static const char CLASSPATH_BT_ADVERTISE_CB[] = "android/bluetooth/le/AdvertiseCallback";
71
72 void CALEServerJNISetContext()
73 {
74     OIC_LOG(DEBUG, TAG, "CALEServerJNISetContext");
75     g_context = (jobject) CANativeJNIGetContext();
76 }
77
78 void CALeServerJniInit()
79 {
80     OIC_LOG(DEBUG, TAG, "CALeServerJniInit");
81     g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
82 }
83
84 CAResult_t CALEServerCreateJniInterfaceObject()
85 {
86     OIC_LOG(DEBUG, TAG, "CALEServerCreateJniInterfaceObject");
87
88     if (!g_context)
89     {
90         OIC_LOG(ERROR, TAG, "g_context is null");
91         return CA_STATUS_FAILED;
92     }
93
94     if (!g_jvm)
95     {
96         OIC_LOG(ERROR, TAG, "g_jvm is null");
97         return CA_STATUS_FAILED;
98     }
99
100     bool isAttached = false;
101     JNIEnv* env;
102     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
103     if (JNI_OK != res)
104     {
105         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
106         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
107
108         if (JNI_OK != res)
109         {
110             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
111             return CA_STATUS_FAILED;
112         }
113         isAttached = true;
114     }
115
116     jclass jni_LEInterface = (*env)->FindClass(env, "org/iotivity/ca/CaLeServerInterface");
117     if (!jni_LEInterface)
118     {
119         OIC_LOG(ERROR, TAG, "Could not get CaLeServerInterface class");
120         goto exit;
121     }
122
123     jmethodID LeInterfaceConstructorMethod = (*env)->GetMethodID(env, jni_LEInterface, "<init>",
124                                                                  "()V");
125     if (!LeInterfaceConstructorMethod)
126     {
127         OIC_LOG(ERROR, TAG, "Could not get CaLeServerInterface constructor method");
128         goto exit;
129     }
130
131     (*env)->NewObject(env, jni_LEInterface, LeInterfaceConstructorMethod, g_context);
132     OIC_LOG(DEBUG, TAG, "Create instance for CaLeServerInterface");
133
134     if (isAttached)
135     {
136         (*g_jvm)->DetachCurrentThread(g_jvm);
137     }
138
139     return CA_STATUS_OK;
140
141     exit:
142
143     if (isAttached)
144     {
145         (*g_jvm)->DetachCurrentThread(g_jvm);
146     }
147
148     return CA_STATUS_FAILED;
149 }
150
151 /**
152  * get the current connection state of the gatt profile to the remote device.
153  * @param[in]   env              JNI interface pointer.
154  * @param[in]   device           bluetooth device object
155  * @return  state of the profile connection.
156  */
157 static jint CALEServerGetConnectionState(JNIEnv *env, jobject device)
158 {
159     OIC_LOG(DEBUG, TAG, "CALEServerGetConnectionState");
160
161     VERIFY_NON_NULL_RET(env, TAG, "env", -1);
162     VERIFY_NON_NULL_RET(device, TAG, "device", -1);
163
164     jclass jni_cid_bluetoothManager = (*env)->FindClass(env, "android/bluetooth/BluetoothManager");
165     if (!jni_cid_bluetoothManager)
166     {
167         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothManager is null");
168         return -1;
169     }
170
171     jmethodID jni_mid_getConnectionState = (*env)->GetMethodID(env, jni_cid_bluetoothManager,
172                                                                "getConnectionState",
173                                                                "(Landroid/bluetooth/BluetoothDevice"
174                                                                ";I)I");
175     if (!jni_mid_getConnectionState)
176     {
177         OIC_LOG(ERROR, TAG, "jni_mid_getConnectionState is null");
178         return -1;
179     }
180
181     if (!g_bluetoothManager)
182     {
183         OIC_LOG(ERROR, TAG, "g_bluetoothManager is null");
184         return -1;
185     }
186
187     jint jni_state = (jint)(*env)->CallIntMethod(env, g_bluetoothManager,
188                                                  jni_mid_getConnectionState,
189                                                  device, GATT_PROFILE);
190     OIC_LOG_V(INFO, TAG, "connection state is %d", jni_state);
191     return jni_state;
192 }
193
194 jobject CALEServerSetResponseData(JNIEnv *env, jbyteArray responseData)
195 {
196     OIC_LOG(DEBUG, TAG, "IN - CALEServerSetResponseData");
197     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
198     VERIFY_NON_NULL_RET(responseData, TAG, "responseData is null", NULL);
199
200     if (!g_bluetoothGattServer)
201     {
202         OIC_LOG(ERROR, TAG, "Check BluetoothGattServer status");
203         return NULL;
204     }
205
206     if (!CALEIsEnableBTAdapter(env))
207     {
208         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
209         return NULL;
210     }
211
212     OIC_LOG(DEBUG, TAG, "CALEServerSetResponseData");
213
214     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
215                                                            "android/bluetooth/BluetoothGattServer");
216     if (!jni_cid_bluetoothGattServer)
217     {
218         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null");
219         return NULL;
220     }
221
222     jclass jni_cid_bluetoothGattService = (*env)->FindClass(env, "android/bluetooth/"
223                                                             "BluetoothGattService");
224     if (!jni_cid_bluetoothGattService)
225     {
226         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattService is null");
227         return NULL;
228     }
229
230     jclass jni_cid_bluetoothGattCharacteristic = (*env)->FindClass(env, "android/bluetooth/"
231                                                                    "BluetoothGattCharacteristic");
232     if (!jni_cid_bluetoothGattCharacteristic)
233     {
234         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattCharacteristic is null");
235         return NULL;
236     }
237
238     jmethodID jni_mid_getService = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
239                                                        "getService",
240                                                        "(Ljava/util/UUID;)Landroid/bluetooth/"
241                                                        "BluetoothGattService;");
242     if (!jni_mid_getService)
243     {
244         OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
245         return NULL;
246     }
247
248     jobject jni_obj_serviceUUID = CALEGetUuidFromString(env, OIC_GATT_SERVICE_UUID);
249     if (!jni_obj_serviceUUID)
250     {
251         OIC_LOG(ERROR, TAG, "jni_obj_serviceUUID is null");
252         return NULL;
253     }
254
255     jobject jni_obj_bluetoothGattService = (*env)->CallObjectMethod(env, g_bluetoothGattServer,
256                                                                     jni_mid_getService,
257                                                                     jni_obj_serviceUUID);
258     if (!jni_obj_bluetoothGattService)
259     {
260         OIC_LOG(ERROR, TAG, "jni_obj_bluetoothGattService is null");
261         return NULL;
262     }
263
264     jmethodID jni_mid_getCharacteristic = (*env)->GetMethodID(env, jni_cid_bluetoothGattService,
265                                                               "getCharacteristic",
266                                                               "(Ljava/util/UUID;)"
267                                                               "Landroid/bluetooth/"
268                                                               "BluetoothGattCharacteristic;");
269     if (!jni_mid_getCharacteristic)
270     {
271         OIC_LOG(ERROR, TAG, "jni_mid_getCharacteristic is null");
272         return NULL;
273     }
274
275     jobject jni_obj_responseUUID = CALEGetUuidFromString(env,
276                                                          OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
277     if (!jni_obj_responseUUID)
278     {
279         OIC_LOG(ERROR, TAG, "jni_obj_responseUUID is null");
280         return NULL;
281     }
282
283     jobject jni_obj_bluetoothGattCharacteristic = (*env)->CallObjectMethod(
284             env, jni_obj_bluetoothGattService, jni_mid_getCharacteristic, jni_obj_responseUUID);
285     if (!jni_obj_bluetoothGattCharacteristic)
286     {
287         OIC_LOG(ERROR, TAG, "jni_obj_bluetoothGattCharacteristic is null");
288         return NULL;
289     }
290
291     jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_bluetoothGattCharacteristic,
292                                                      "setValue", "([B)Z");
293     if (!jni_mid_setValue)
294     {
295         OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
296         return NULL;
297     }
298
299     jboolean jni_boolean_setValue = (*env)->CallBooleanMethod(env,
300                                                               jni_obj_bluetoothGattCharacteristic,
301                                                               jni_mid_setValue, responseData);
302     if (JNI_FALSE == jni_boolean_setValue)
303     {
304         OIC_LOG(ERROR, TAG, "Fail to set response data");
305     }
306
307     OIC_LOG(DEBUG, TAG, "OUT - CALEServerSetResponseData");
308     return jni_obj_bluetoothGattCharacteristic;
309 }
310
311 CAResult_t CALEServerSendResponseData(JNIEnv *env, jobject device, jobject responseData)
312 {
313     OIC_LOG(DEBUG, TAG, "CALEServerSendResponseData");
314     VERIFY_NON_NULL(responseData, TAG, "responseData is null");
315     VERIFY_NON_NULL(device, TAG, "device is null");
316     VERIFY_NON_NULL(env, TAG, "env is null");
317
318     if (!CALEIsEnableBTAdapter(env))
319     {
320         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
321         return CA_ADAPTER_NOT_ENABLED;
322     }
323
324     if (STATE_CONNECTED != CALEServerGetConnectionState(env, device))
325     {
326         OIC_LOG(ERROR, TAG, "it is not connected state");
327         return CA_STATUS_FAILED;
328     }
329
330     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
331                                                            "android/bluetooth/BluetoothGattServer");
332     if (!jni_cid_bluetoothGattServer)
333     {
334         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null");
335         return CA_STATUS_FAILED;
336     }
337
338     jmethodID jni_mid_notifyCharacteristicChanged = (*env)->GetMethodID(
339             env, jni_cid_bluetoothGattServer, "notifyCharacteristicChanged",
340             "(Landroid/bluetooth/BluetoothDevice;"
341             "Landroid/bluetooth/BluetoothGattCharacteristic;Z)Z");
342     if (!jni_mid_notifyCharacteristicChanged)
343     {
344         OIC_LOG(ERROR, TAG, "jni_mid_notifyCharacteristicChanged is null");
345         return CA_STATUS_FAILED;
346     }
347
348     OIC_LOG(DEBUG, TAG, "CALL API - notifyCharacteristicChanged");
349
350     jboolean jni_boolean_notifyCharacteristicChanged = (*env)->CallBooleanMethod(
351             env, g_bluetoothGattServer, jni_mid_notifyCharacteristicChanged, device, responseData,
352             JNI_FALSE);
353     if (JNI_FALSE == jni_boolean_notifyCharacteristicChanged)
354     {
355         OIC_LOG(ERROR, TAG, "Fail to notify characteristic");
356         return CA_SEND_FAILED;
357     }
358
359     OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
360     ca_mutex_lock(g_threadSendNotifyMutex);
361     if (!g_isSignalSetFlag)
362     {
363         OIC_LOG(DEBUG, TAG, "wait for callback to notify notifyCharacteristic is success");
364         if (0 != ca_cond_wait_for(g_threadSendNotifyCond, g_threadSendNotifyMutex,
365                                   WAIT_TIME_WRITE_CHARACTERISTIC))
366         {
367             OIC_LOG(ERROR, TAG, "there is no response. notifyCharacteristic has failed");
368             ca_mutex_unlock(g_threadSendNotifyMutex);
369             return CA_STATUS_FAILED;
370         }
371     }
372     // reset flag set by writeCharacteristic Callback
373     g_isSignalSetFlag = false;
374     ca_mutex_unlock(g_threadSendNotifyMutex);
375     OIC_LOG(INFO, TAG, "notifyCharacteristic success");
376     return CA_STATUS_OK;
377 }
378
379 CAResult_t CALEServerSendResponse(JNIEnv *env, jobject device, jint requestId, jint status,
380                                         jint offset, jbyteArray value)
381 {
382     OIC_LOG(DEBUG, TAG, "IN - CALEServerSendResponse");
383     VERIFY_NON_NULL(env, TAG, "env is null");
384     VERIFY_NON_NULL(device, TAG, "device is null");
385     VERIFY_NON_NULL(value, TAG, "value is null");
386
387     OIC_LOG(DEBUG, TAG, "CALEServerSendResponse");
388
389     if (!CALEIsEnableBTAdapter(env))
390     {
391         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
392         return CA_ADAPTER_NOT_ENABLED;
393     }
394
395     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
396                                                            "android/bluetooth/BluetoothGattServer");
397     if (!jni_cid_bluetoothGattServer)
398     {
399         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null");
400         return CA_STATUS_FAILED;
401     }
402
403     jmethodID jni_mid_sendResponse = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
404                                                          "sendResponse",
405                                                          "(Landroid/bluetooth/BluetoothDevice;"
406                                                          "III[B)Z");
407     if (!jni_mid_sendResponse)
408     {
409         OIC_LOG(ERROR, TAG, "jni_mid_sendResponse is null");
410         return CA_STATUS_FAILED;
411     }
412
413     jboolean jni_boolean_sendResponse = (*env)->CallBooleanMethod(env, g_bluetoothGattServer,
414                                                                   jni_mid_sendResponse, device,
415                                                                   requestId, status, offset,
416                                                                   value);
417     if (JNI_FALSE == jni_boolean_sendResponse)
418     {
419         OIC_LOG(ERROR, TAG, "Fail to send response for gatt characteristic write request");
420         return CA_SEND_FAILED;
421     }
422
423     OIC_LOG(DEBUG, TAG, "OUT - CALEServerSendResponse");
424     return CA_STATUS_OK;
425 }
426
427 CAResult_t CALEStartAdvertise()
428 {
429     if (!g_jvm)
430     {
431         OIC_LOG(ERROR, TAG, "g_jvm is null");
432         return CA_STATUS_FAILED;
433     }
434
435     bool isAttached = false;
436     JNIEnv* env;
437     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
438     if (JNI_OK != res)
439     {
440         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
441         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
442
443         if (JNI_OK != res)
444         {
445             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
446             return CA_STATUS_FAILED;
447         }
448         isAttached = true;
449     }
450
451     // start advertise
452     CAResult_t ret = CALEServerStartAdvertise(env, g_leAdvertiseCallback);
453     if (CA_STATUS_OK != ret)
454     {
455         OIC_LOG(ERROR, TAG, "CALEServerStartAdvertise has failed");
456     }
457
458     if (isAttached)
459     {
460         (*g_jvm)->DetachCurrentThread(g_jvm);
461     }
462     return ret;
463 }
464
465 CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback)
466 {
467     OIC_LOG(DEBUG, TAG, "IN - CALEServerStartAdvertise");
468     VERIFY_NON_NULL(env, TAG, "env is null");
469     VERIFY_NON_NULL(advertiseCallback, TAG, "advertiseCallback is null");
470
471     if (!CALEIsEnableBTAdapter(env))
472     {
473         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
474         return CA_ADAPTER_NOT_ENABLED;
475     }
476
477     jclass jni_cid_AdvertiseSettings = (*env)->FindClass(env,
478                                                          "android/bluetooth/le/"
479                                                          "AdvertiseSettings$Builder");
480     if (!jni_cid_AdvertiseSettings)
481     {
482         OIC_LOG(ERROR, TAG, "jni_cid_AdvertiseSettings is null");
483         return CA_STATUS_FAILED;
484     }
485
486     jmethodID jni_mid_AdvertiseSettings = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings,
487                                                               "<init>", "()V");
488     if (!jni_mid_AdvertiseSettings)
489     {
490         OIC_LOG(ERROR, TAG, "jni_mid_AdvertiseSettings is null");
491         return CA_STATUS_FAILED;
492     }
493
494     jobject jni_AdvertiseSettings = (*env)->NewObject(env, jni_cid_AdvertiseSettings,
495                                                       jni_mid_AdvertiseSettings);
496     if (!jni_AdvertiseSettings)
497     {
498         OIC_LOG(ERROR, TAG, "jni_AdvertiseSettings is null");
499         return CA_STATUS_FAILED;
500     }
501
502     jmethodID jni_mid_setAdvertiseMode = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings,
503                                                              "setAdvertiseMode",
504                                                              "(I)Landroid/bluetooth/le/"
505                                                              "AdvertiseSettings$Builder;");
506     if (!jni_mid_setAdvertiseMode)
507     {
508         OIC_LOG(ERROR, TAG, "jni_mid_setAdvertiseMode is null");
509         return CA_STATUS_FAILED;
510     }
511
512     // 0: Low power, 1: Balanced
513     jobject jni_obj_setAdvertiseMode = (*env)->CallObjectMethod(env, jni_AdvertiseSettings,
514                                                                 jni_mid_setAdvertiseMode, 0);
515     if (!jni_obj_setAdvertiseMode)
516     {
517         OIC_LOG(ERROR, TAG, "jni_obj_setAdvertiseMode is null");
518         return CA_STATUS_FAILED;
519     }
520
521     jmethodID jni_mid_setConnectable = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings,
522                                                            "setConnectable",
523                                                            "(Z)Landroid/bluetooth/le/"
524                                                            "AdvertiseSettings$Builder;");
525     if (!jni_mid_setConnectable)
526     {
527         OIC_LOG(ERROR, TAG, "jni_mid_setConnectable is null");
528         return CA_STATUS_FAILED;
529     }
530
531     jobject jni_obj_setConnectable = (*env)->CallObjectMethod(env, jni_AdvertiseSettings,
532                                                               jni_mid_setConnectable, JNI_TRUE);
533     if (!jni_obj_setConnectable)
534     {
535         OIC_LOG(ERROR, TAG, "jni_obj_setConnectable is null");
536         return CA_STATUS_FAILED;
537     }
538
539     jmethodID jni_mid_setTimeout = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings, "setTimeout",
540                                                        "(I)Landroid/bluetooth/le/"
541                                                        "AdvertiseSettings$Builder;");
542     if (!jni_mid_setTimeout)
543     {
544         OIC_LOG(ERROR, TAG, "jni_mid_setTimeout is null");
545         return CA_STATUS_FAILED;
546     }
547
548     //A value of 0 will disable the time limit
549     jobject jni_obj_setTimeout = (*env)->CallObjectMethod(env, jni_AdvertiseSettings,
550                                                           jni_mid_setTimeout, 0);
551     if (!jni_obj_setTimeout)
552     {
553         OIC_LOG(ERROR, TAG, "jni_obj_setTimeout is null");
554         return CA_STATUS_FAILED;
555     }
556
557     jclass jni_cid_AdvertiseDataBuilder = (*env)->FindClass(env,
558                                                             "android/bluetooth/le/"
559                                                             "AdvertiseData$Builder");
560     if (!jni_cid_AdvertiseDataBuilder)
561     {
562         OIC_LOG(ERROR, TAG, "jni_cid_AdvertiseDataBuilder is null");
563         return CA_STATUS_FAILED;
564     }
565
566     jmethodID jni_mid_AdvertiseDataBuilder = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder,
567                                                                  "<init>", "()V");
568     if (!jni_mid_AdvertiseDataBuilder)
569     {
570         OIC_LOG(ERROR, TAG, "jni_mid_AdvertiseDataBuilder is null");
571         return CA_STATUS_FAILED;
572     }
573
574     jobject jni_AdvertiseDataBuilder = (*env)->NewObject(env, jni_cid_AdvertiseDataBuilder,
575                                                          jni_mid_AdvertiseDataBuilder);
576     if (!jni_AdvertiseDataBuilder)
577     {
578         OIC_LOG(ERROR, TAG, "jni_AdvertiseDataBuilder is null");
579         return CA_STATUS_FAILED;
580     }
581
582     jobject jni_AdvertiseDataBuilderForScanRsp = (*env)->NewObject(env,
583                                                                    jni_cid_AdvertiseDataBuilder,
584                                                                    jni_mid_AdvertiseDataBuilder);
585     if (!jni_AdvertiseDataBuilderForScanRsp)
586     {
587         OIC_LOG(ERROR, TAG, "jni_AdvertiseDataBuilderForScanRsp is null");
588         return CA_STATUS_FAILED;
589     }
590
591     jobject jni_obj_serviceUUID = CALEGetUuidFromString(env, OIC_GATT_SERVICE_UUID);
592     if (!jni_obj_serviceUUID)
593     {
594         OIC_LOG(ERROR, TAG, "jni_obj_serviceUUID is null");
595         return CA_STATUS_FAILED;
596     }
597
598     jobject jni_ParcelUuid = CALEGetParcelUuid(env, jni_obj_serviceUUID);
599     if (!jni_ParcelUuid)
600     {
601         OIC_LOG(ERROR, TAG, "jni_ParcelUuid is null");
602         return CA_STATUS_FAILED;
603     }
604
605     jmethodID jni_mid_addServiceUuid = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder,
606                                                            "addServiceUuid",
607                                                            "(Landroid/os/ParcelUuid;)Landroid/"
608                                                            "bluetooth/le/AdvertiseData$Builder;");
609     if (!jni_mid_addServiceUuid)
610     {
611         OIC_LOG(ERROR, TAG, "jni_mid_addServiceUuid is null");
612         return CA_STATUS_FAILED;
613     }
614
615     jobject jni_obj_addServiceUuid = (*env)->CallObjectMethod(env, jni_AdvertiseDataBuilder,
616                                                               jni_mid_addServiceUuid,
617                                                               jni_ParcelUuid);
618     if (!jni_obj_addServiceUuid)
619     {
620         OIC_LOG(ERROR, TAG, "jni_obj_addServiceUuid is null");
621         return CA_STATUS_FAILED;
622     }
623
624     // Device name has to be included in advertise packet after Android API 23
625     OIC_LOG(DEBUG, TAG, "device name will be added into advertise packet");
626     jmethodID jni_mid_setIncludeDeviceName = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder,
627                                                                  "setIncludeDeviceName",
628                                                                  "(Z)Landroid/"
629                                                                  "bluetooth/le/"
630                                                                  "AdvertiseData$Builder;");
631     if (!jni_mid_setIncludeDeviceName)
632     {
633         OIC_LOG(ERROR, TAG, "jni_mid_setIncludeDeviceName is null");
634         return CA_STATUS_FAILED;
635     }
636
637     jobject jni_obj_setIncludeDeviceName  = (*env)->CallObjectMethod(env,
638                                                                jni_AdvertiseDataBuilderForScanRsp,
639                                                                jni_mid_setIncludeDeviceName,
640                                                                JNI_TRUE);
641     if (!jni_obj_setIncludeDeviceName)
642     {
643         OIC_LOG(ERROR, TAG, "jni_obj_setIncludeDeviceName is null");
644         return CA_STATUS_FAILED;
645     }
646
647     jclass jni_cid_BTAdapter = (*env)->FindClass(env, "android/bluetooth/BluetoothAdapter");
648     if (!jni_cid_BTAdapter)
649     {
650         OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
651         return CA_STATUS_FAILED;
652     }
653
654     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
655                                                                     "getDefaultAdapter",
656                                                                     "()Landroid/bluetooth/"
657                                                                     "BluetoothAdapter;");
658     if (!jni_mid_getDefaultAdapter)
659     {
660         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
661         return CA_STATUS_FAILED;
662     }
663
664     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
665                                                                jni_mid_getDefaultAdapter);
666     if (!jni_obj_BTAdapter)
667     {
668         OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
669         return CA_STATUS_FAILED;
670     }
671
672     jmethodID jni_mid_getBluetoothLeAdvertiser = (*env)->GetMethodID(env, jni_cid_BTAdapter,
673                                                                      "getBluetoothLeAdvertiser",
674                                                                      "()Landroid/bluetooth/le/"
675                                                                      "BluetoothLeAdvertiser;");
676     if (!jni_mid_getBluetoothLeAdvertiser)
677     {
678         OIC_LOG(ERROR, TAG, "jni_mid_getBluetoothLeAdvertiser is null");
679         return CA_STATUS_FAILED;
680     }
681
682     jobject jni_obj_getBluetoothLeAdvertiser = (*env)->CallObjectMethod(
683             env, jni_obj_BTAdapter, jni_mid_getBluetoothLeAdvertiser);
684     if (!jni_obj_getBluetoothLeAdvertiser)
685     {
686         OIC_LOG(ERROR, TAG, "jni_obj_getBluetoothLeAdvertiser is null");
687         return CA_STATUS_FAILED;
688     }
689
690     jmethodID jni_mid_build_LeAdvertiseSettings = (*env)->GetMethodID(env,
691                                                                       jni_cid_AdvertiseSettings,
692                                                                       "build",
693                                                                       "()Landroid/bluetooth/le/"
694                                                                       "AdvertiseSettings;");
695     if (!jni_mid_build_LeAdvertiseSettings)
696     {
697         OIC_LOG(ERROR, TAG, "jni_mid_build_LeAdvertiseSettings is null");
698         return CA_STATUS_FAILED;
699     }
700
701     jobject jni_obj_build_LeAdvertiseSettings = (*env)->CallObjectMethod(
702             env, jni_AdvertiseSettings, jni_mid_build_LeAdvertiseSettings);
703     if (!jni_obj_build_LeAdvertiseSettings)
704     {
705         OIC_LOG(ERROR, TAG, "jni_obj_build_LeAdvertiseSettings is null");
706         return CA_STATUS_FAILED;
707     }
708
709     jmethodID jni_mid_build_LeAdvertiseData = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder,
710                                                                   "build",
711                                                                   "()Landroid/bluetooth/le/"
712                                                                   "AdvertiseData;");
713     if (!jni_mid_build_LeAdvertiseData)
714     {
715         OIC_LOG(ERROR, TAG, "jni_mid_build_LeAdvertiseData is null");
716         return CA_STATUS_FAILED;
717     }
718
719     jobject jni_obj_build_LeAdvertiseData = (*env)->CallObjectMethod(env, jni_AdvertiseDataBuilder,
720                                                                      jni_mid_build_LeAdvertiseData);
721     if (!jni_obj_build_LeAdvertiseData)
722     {
723         OIC_LOG(ERROR, TAG, "jni_obj_build_LeAdvertiseData is null");
724         return CA_STATUS_FAILED;
725     }
726
727     jobject jni_obj_build_LeAdvertiseDataForScanRsp = (*env)->CallObjectMethod(env,
728                                                                 jni_AdvertiseDataBuilderForScanRsp,
729                                                                 jni_mid_build_LeAdvertiseData);
730     if (!jni_obj_build_LeAdvertiseDataForScanRsp)
731     {
732         OIC_LOG(ERROR, TAG, "jni_obj_build_LeAdvertiseDataForScanRsp is null");
733         return CA_STATUS_FAILED;
734     }
735
736     jclass jni_cid_leAdvertiser = (*env)->FindClass(env,
737                                                     "android/bluetooth/le/BluetoothLeAdvertiser");
738     if (!jni_cid_leAdvertiser)
739     {
740         OIC_LOG(ERROR, TAG, "jni_cid_leAdvertiser is null");
741         return CA_STATUS_FAILED;
742     }
743
744     jmethodID jni_mid_startAdvertising = (*env)->GetMethodID(env, jni_cid_leAdvertiser,
745                                                                  "startAdvertising",
746                                                                  "(Landroid/bluetooth/le/"
747                                                                  "AdvertiseSettings;Landroid/bluetooth/"
748                                                                  "le/AdvertiseData;Landroid/bluetooth/"
749                                                                  "le/AdvertiseData;Landroid/bluetooth/"
750                                                                  "le/AdvertiseCallback;)V");
751     if (!jni_mid_startAdvertising)
752     {
753         OIC_LOG(ERROR, TAG, "jni_mid_startAdvertising is null");
754         return CA_STATUS_FAILED;
755     }
756
757     (*env)->CallVoidMethod(env, jni_obj_getBluetoothLeAdvertiser, jni_mid_startAdvertising,
758                            jni_obj_build_LeAdvertiseSettings, jni_obj_build_LeAdvertiseData,
759                            jni_obj_build_LeAdvertiseDataForScanRsp, advertiseCallback);
760
761     if ((*env)->ExceptionCheck(env))
762     {
763         OIC_LOG(ERROR, TAG, "StartAdvertising has failed");
764         (*env)->ExceptionDescribe(env);
765         (*env)->ExceptionClear(env);
766         return CA_STATUS_FAILED;
767     }
768
769     OIC_LOG(DEBUG, TAG, "Advertising started!!");
770
771     OIC_LOG(DEBUG, TAG, "OUT - CALEServerStartAdvertise");
772     return CA_STATUS_OK;
773 }
774
775 CAResult_t CALEServerStopAdvertise(JNIEnv *env, jobject advertiseCallback)
776 {
777     OIC_LOG(DEBUG, TAG, "LEServerStopAdvertise");
778     VERIFY_NON_NULL(env, TAG, "env is null");
779     VERIFY_NON_NULL(advertiseCallback, TAG, "advertiseCallback is null");
780
781     if (!CALEIsEnableBTAdapter(env))
782     {
783         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
784         return CA_ADAPTER_NOT_ENABLED;
785     }
786
787     jclass jni_cid_BTAdapter = (*env)->FindClass(env, "android/bluetooth/BluetoothAdapter");
788     if (!jni_cid_BTAdapter)
789     {
790         OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
791         return CA_STATUS_FAILED;
792     }
793
794     jclass jni_cid_leAdvertiser = (*env)->FindClass(env,
795                                                     "android/bluetooth/le/BluetoothLeAdvertiser");
796     if (!jni_cid_leAdvertiser)
797     {
798         OIC_LOG(ERROR, TAG, "jni_cid_leAdvertiser is null");
799         return CA_STATUS_FAILED;
800     }
801
802     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
803                                                                     "getDefaultAdapter",
804                                                                     "()Landroid/bluetooth/"
805                                                                     "BluetoothAdapter;");
806     if (!jni_mid_getDefaultAdapter)
807     {
808         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
809         return CA_STATUS_FAILED;
810     }
811
812     jmethodID jni_mid_getBTLeAdvertiser = (*env)->GetMethodID(env, jni_cid_BTAdapter,
813                                                                      "getBluetoothLeAdvertiser",
814                                                                      "()Landroid/bluetooth/le/"
815                                                                      "BluetoothLeAdvertiser;");
816     if (!jni_mid_getBTLeAdvertiser)
817     {
818         OIC_LOG(ERROR, TAG, "jni_mid_getBTLeAdvertiser is null");
819         return CA_STATUS_FAILED;
820     }
821
822     jmethodID jni_mid_stopAdvertising = (*env)->GetMethodID(env, jni_cid_leAdvertiser,
823                                                             "stopAdvertising",
824                                                             "(Landroid/bluetooth/le/"
825                                                             "AdvertiseCallback;)V");
826     if (!jni_mid_stopAdvertising)
827     {
828         OIC_LOG(ERROR, TAG, "jni_mid_stopAdvertising is null");
829         return CA_STATUS_FAILED;
830     }
831
832     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
833                                                                jni_mid_getDefaultAdapter);
834     if (!jni_obj_BTAdapter)
835     {
836         OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
837         return CA_STATUS_FAILED;
838     }
839
840     jobject jni_obj_getBluetoothLeAdvertiser = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
841                                                                         jni_mid_getBTLeAdvertiser);
842     if (!jni_obj_getBluetoothLeAdvertiser)
843     {
844         OIC_LOG(ERROR, TAG, "jni_obj_getBluetoothLeAdvertiser is null");
845         return CA_STATUS_FAILED;
846     }
847
848     (*env)->CallVoidMethod(env, jni_obj_getBluetoothLeAdvertiser, jni_mid_stopAdvertising,
849                            advertiseCallback);
850     if ((*env)->ExceptionCheck(env))
851     {
852         OIC_LOG(ERROR, TAG, "getBluetoothLeAdvertiser has failed");
853         (*env)->ExceptionDescribe(env);
854         (*env)->ExceptionClear(env);
855         return CA_STATUS_FAILED;
856     }
857
858     OIC_LOG(DEBUG, TAG, "Advertising stopped!!");
859     return CA_STATUS_OK;
860 }
861
862 CAResult_t CALEServerStartGattServer(JNIEnv *env, jobject gattServerCallback)
863 {
864     OIC_LOG(DEBUG, TAG, "IN - CALEServerStartGattServer");
865     VERIFY_NON_NULL(env, TAG, "env is null");
866     VERIFY_NON_NULL(gattServerCallback, TAG, "gattServerCallback is null");
867
868     if (!CALEIsEnableBTAdapter(env))
869     {
870         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
871         return CA_ADAPTER_NOT_ENABLED;
872     }
873
874     if (g_isStartServer)
875     {
876         OIC_LOG(DEBUG, TAG, "Gatt server already started");
877     }
878
879     g_bluetoothGattServerCallback = (*env)->NewGlobalRef(env, gattServerCallback);
880
881     // open gatt server
882     jobject bluetoothGattServer = CALEServerOpenGattServer(env);
883     if (!bluetoothGattServer)
884     {
885         OIC_LOG(ERROR, TAG, "bluetoothGattServer is null");
886         return CA_STATUS_FAILED;
887     }
888
889     g_bluetoothGattServer = (*env)->NewGlobalRef(env, bluetoothGattServer);
890     if (!g_bluetoothGattServer)
891     {
892         OIC_LOG(ERROR, TAG, "g_bluetoothGattServer is null");
893         return CA_STATUS_FAILED;
894     }
895
896     // create gatt service
897     jobject bluetoothGattService = CALEServerCreateGattService(env);
898     if (!bluetoothGattService)
899     {
900         OIC_LOG(ERROR, TAG, "bluetoothGattService is null");
901         return CA_STATUS_FAILED;
902     }
903
904     // add gatt service
905     CAResult_t res = CALEServerAddGattService(env, g_bluetoothGattServer,
906                                               bluetoothGattService);
907     if (CA_STATUS_OK != res)
908     {
909         OIC_LOG(ERROR, TAG, "CALEServerAddGattService has failed");
910     }
911     return res;
912 }
913
914 jobject CALEServerOpenGattServer(JNIEnv *env)
915 {
916     OIC_LOG(DEBUG, TAG, "IN - CALEServerOpenGattServer");
917     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
918
919     if (!CALEIsEnableBTAdapter(env))
920     {
921         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
922         return NULL;
923     }
924
925     jclass jni_cid_context = (*env)->FindClass(env, "android/content/Context");
926     if (!jni_cid_context)
927     {
928         OIC_LOG(ERROR, TAG, "jni_cid_context is null");
929         return NULL;
930     }
931
932     jclass jni_cid_bluetoothManager = (*env)->FindClass(env, "android/bluetooth/BluetoothManager");
933     if (!jni_cid_bluetoothManager)
934     {
935         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothManager is null");
936         return NULL;
937     }
938
939     jfieldID jni_fid_bluetoothService = (*env)->GetStaticFieldID(env, jni_cid_context,
940                                                                  "BLUETOOTH_SERVICE",
941                                                                  "Ljava/lang/String;");
942     if (!jni_fid_bluetoothService)
943     {
944         OIC_LOG(ERROR, TAG, "jni_fid_bluetoothService is null");
945         return NULL;
946     }
947
948     jmethodID jni_mid_getSystemService = (*env)->GetMethodID(env, jni_cid_context,
949                                                              "getSystemService",
950                                                              "(Ljava/lang/String;)"
951                                                              "Ljava/lang/Object;");
952     if (!jni_mid_getSystemService)
953     {
954         OIC_LOG(ERROR, TAG, "jni_mid_getSystemService is null");
955         return NULL;
956     }
957
958     jmethodID jni_mid_openGattServer = (*env)->GetMethodID(env, jni_cid_bluetoothManager,
959                                                            "openGattServer",
960                                                            "(Landroid/content/Context;"
961                                                            "Landroid/bluetooth/"
962                                                            "BluetoothGattServerCallback;)"
963                                                            "Landroid/bluetooth/"
964                                                            "BluetoothGattServer;");
965     if (!jni_mid_openGattServer)
966     {
967         OIC_LOG(ERROR, TAG, "jni_mid_openGattServer is null");
968         return NULL;
969     }
970
971     jobject jni_obj_bluetoothService = (*env)->GetStaticObjectField(env, jni_cid_context,
972                                                                     jni_fid_bluetoothService);
973     if (!jni_obj_bluetoothService)
974     {
975         OIC_LOG(ERROR, TAG, "jni_obj_bluetoothService is null");
976         return NULL;
977     }
978
979     jobject jni_obj_bluetoothManager = (*env)->CallObjectMethod(env, g_context,
980                                                                 jni_mid_getSystemService,
981                                                                 jni_obj_bluetoothService);
982     if (!jni_obj_bluetoothManager)
983     {
984         OIC_LOG(ERROR, TAG, "jni_obj_bluetoothManager is null");
985         return NULL;
986     }
987
988     if (g_bluetoothManager)
989     {
990         (*env)->DeleteGlobalRef(env, g_bluetoothManager);
991     }
992     g_bluetoothManager = (*env)->NewGlobalRef(env, jni_obj_bluetoothManager);
993
994     jobject jni_obj_bluetoothGattServer = (*env)->CallObjectMethod(env, jni_obj_bluetoothManager,
995                                                                    jni_mid_openGattServer,
996                                                                    g_context,
997                                                                    g_bluetoothGattServerCallback);
998     if (!jni_obj_bluetoothGattServer)
999     {
1000         OIC_LOG(ERROR, TAG, "jni_obj_bluetoothGattServer is null");
1001         return NULL;
1002     }
1003
1004     OIC_LOG(DEBUG, TAG, "OUT - CALEServerOpenGattServer");
1005     return jni_obj_bluetoothGattServer;
1006 }
1007
1008 jobject CALEServerCreateGattService(JNIEnv *env)
1009 {
1010     OIC_LOG(DEBUG, TAG, "IN - CALEServerCreateGattService");
1011     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1012
1013     if (!CALEIsEnableBTAdapter(env))
1014     {
1015         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1016         return NULL;
1017     }
1018
1019     jclass jni_cid_bluetoothGattService = (*env)->FindClass(env, "android/bluetooth/"
1020                                                             "BluetoothGattService");
1021     if (!jni_cid_bluetoothGattService)
1022     {
1023         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattService is null");
1024         return NULL;
1025     }
1026
1027     jclass jni_cid_bluetoothGattCharacteristic = (*env)->FindClass(env, "android/bluetooth/"
1028                                                                    "BluetoothGattCharacteristic");
1029     if (!jni_cid_bluetoothGattCharacteristic)
1030     {
1031         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattCharacteristic is null");
1032         return NULL;
1033     }
1034
1035     jfieldID jni_fid_serviceType = (*env)->GetStaticFieldID(env, jni_cid_bluetoothGattService,
1036                                                             "SERVICE_TYPE_PRIMARY", "I");
1037     if (!jni_fid_serviceType)
1038     {
1039         OIC_LOG(ERROR, TAG, "jni_fid_serviceType is null");
1040         return NULL;
1041     }
1042
1043     jfieldID jni_fid_readProperties = (*env)->GetStaticFieldID(env,
1044                                                                jni_cid_bluetoothGattCharacteristic,
1045                                                                "PROPERTY_NOTIFY", "I");
1046     if (!jni_fid_readProperties)
1047     {
1048         OIC_LOG(ERROR, TAG, "jni_fid_readProperties is null");
1049         return NULL;
1050     }
1051
1052     jfieldID jni_fid_writeProperties = (*env)->GetStaticFieldID(env,
1053                                                                 jni_cid_bluetoothGattCharacteristic,
1054                                                                 "PROPERTY_WRITE_NO_RESPONSE", "I");
1055     if (!jni_fid_writeProperties)
1056     {
1057         OIC_LOG(ERROR, TAG, "jni_fid_writeProperties is null");
1058         return NULL;
1059     }
1060
1061     jfieldID jni_fid_readPermissions = (*env)->GetStaticFieldID(env,
1062                                                                 jni_cid_bluetoothGattCharacteristic,
1063                                                                 "PERMISSION_READ", "I");
1064     if (!jni_fid_readPermissions)
1065     {
1066         OIC_LOG(ERROR, TAG, "jni_fid_readPermissions is null");
1067         return NULL;
1068     }
1069
1070     jfieldID jni_fid_writePermissions = (*env)->GetStaticFieldID(
1071             env, jni_cid_bluetoothGattCharacteristic, "PERMISSION_WRITE", "I");
1072     if (!jni_fid_writePermissions)
1073     {
1074         OIC_LOG(ERROR, TAG, "jni_fid_writePermissions is null");
1075         return NULL;
1076     }
1077
1078     jmethodID jni_mid_bluetoothGattService = (*env)->GetMethodID(env, jni_cid_bluetoothGattService,
1079                                                                  "<init>", "(Ljava/util/UUID;I)V");
1080     if (!jni_mid_bluetoothGattService)
1081     {
1082         OIC_LOG(ERROR, TAG, "jni_mid_bluetoothGattService is null");
1083         return NULL;
1084     }
1085
1086     jmethodID jni_mid_addCharacteristic = (*env)->GetMethodID(env, jni_cid_bluetoothGattService,
1087                                                               "addCharacteristic",
1088                                                               "(Landroid/bluetooth/"
1089                                                               "BluetoothGattCharacteristic;)Z");
1090     if (!jni_mid_addCharacteristic)
1091     {
1092         OIC_LOG(ERROR, TAG, "jni_mid_addCharacteristic is null");
1093         return NULL;
1094     }
1095
1096     jmethodID jni_mid_bluetoothGattCharacteristic = (*env)->GetMethodID(
1097             env, jni_cid_bluetoothGattCharacteristic, "<init>", "(Ljava/util/UUID;II)V");
1098     if (!jni_mid_bluetoothGattCharacteristic)
1099     {
1100         OIC_LOG(ERROR, TAG, "jni_mid_bluetoothGattCharacteristic is null");
1101         return NULL;
1102     }
1103
1104     jobject jni_obj_serviceUUID = CALEGetUuidFromString(env, OIC_GATT_SERVICE_UUID);
1105     if (!jni_obj_serviceUUID)
1106     {
1107         OIC_LOG(ERROR, TAG, "jni_obj_serviceUUID is null");
1108         return NULL;
1109     }
1110
1111     jint jni_int_serviceType = (*env)->GetStaticIntField(env, jni_cid_bluetoothGattService,
1112                                                          jni_fid_serviceType);
1113     jobject jni_bluetoothGattService = (*env)->NewObject(env, jni_cid_bluetoothGattService,
1114                                                          jni_mid_bluetoothGattService,
1115                                                          jni_obj_serviceUUID, jni_int_serviceType);
1116     if (!jni_bluetoothGattService)
1117     {
1118         OIC_LOG(ERROR, TAG, "jni_bluetoothGattService is null");
1119         return NULL;
1120     }
1121
1122     jobject jni_obj_readUuid = CALEGetUuidFromString(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
1123     if (!jni_obj_readUuid)
1124     {
1125         OIC_LOG(ERROR, TAG, "jni_obj_readUuid is null");
1126         return NULL;
1127     }
1128
1129     jint jni_int_readProperties = (*env)->GetStaticIntField(env,
1130                                                             jni_cid_bluetoothGattCharacteristic,
1131                                                             jni_fid_readProperties);
1132
1133     jint jni_int_readPermissions = (*env)->GetStaticIntField(env,
1134                                                              jni_cid_bluetoothGattCharacteristic,
1135                                                              jni_fid_readPermissions);
1136
1137     jint jni_int_writePermissions = (*env)->GetStaticIntField(env,
1138                                                               jni_cid_bluetoothGattCharacteristic,
1139                                                               jni_fid_writePermissions);
1140
1141     jobject jni_readCharacteristic = (*env)->NewObject(env, jni_cid_bluetoothGattCharacteristic,
1142                                                        jni_mid_bluetoothGattCharacteristic,
1143                                                        jni_obj_readUuid, jni_int_readProperties,
1144                                                        jni_int_readPermissions|
1145                                                        jni_int_writePermissions);
1146     if (!jni_readCharacteristic)
1147     {
1148         OIC_LOG(ERROR, TAG, "jni_readCharacteristic is null");
1149         return NULL;
1150     }
1151
1152     jboolean jni_boolean_addReadCharacteristic = (*env)->CallBooleanMethod(
1153             env, jni_bluetoothGattService, jni_mid_addCharacteristic, jni_readCharacteristic);
1154     if (!jni_boolean_addReadCharacteristic)
1155     {
1156         OIC_LOG(ERROR, TAG, "jni_boolean_addReadCharacteristic is null");
1157         return NULL;
1158     }
1159
1160     jobject jni_obj_writeUuid = CALEGetUuidFromString(env, OIC_GATT_CHARACTERISTIC_REQUEST_UUID);
1161     if (!jni_obj_writeUuid)
1162     {
1163         OIC_LOG(ERROR, TAG, "jni_obj_bluetoothGattServer is null");
1164         return NULL;
1165     }
1166
1167     jint jni_int_writeProperties = (*env)->GetStaticIntField(env,
1168                                                              jni_cid_bluetoothGattCharacteristic,
1169                                                              jni_fid_writeProperties);
1170
1171     jobject jni_writeCharacteristic = (*env)->NewObject(env, jni_cid_bluetoothGattCharacteristic,
1172                                                         jni_mid_bluetoothGattCharacteristic,
1173                                                         jni_obj_writeUuid, jni_int_writeProperties,
1174                                                         jni_int_writePermissions);
1175     if (!jni_writeCharacteristic)
1176     {
1177         OIC_LOG(ERROR, TAG, "jni_writeCharacteristic is null");
1178         return NULL;
1179     }
1180
1181     jboolean jni_boolean_addWriteCharacteristic = (*env)->CallBooleanMethod(
1182             env, jni_bluetoothGattService, jni_mid_addCharacteristic, jni_writeCharacteristic);
1183     if (JNI_FALSE == jni_boolean_addWriteCharacteristic)
1184     {
1185         OIC_LOG(ERROR, TAG, "Fail to add jni_boolean_addReadCharacteristic");
1186         return NULL;
1187     }
1188
1189     OIC_LOG(DEBUG, TAG, "OUT - CALEServerCreateGattService");
1190     return jni_bluetoothGattService;
1191 }
1192
1193 CAResult_t CALEServerAddDescriptor(JNIEnv *env, jobject characteristic)
1194 {
1195     OIC_LOG(DEBUG, TAG, "CALEServerAddDescriptor");
1196     VERIFY_NON_NULL(env, TAG, "env is null");
1197     VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
1198
1199     jclass jni_cid_bluetoothGattDescriptor = (*env)->FindClass(env, "android/bluetooth/"
1200                                                                "BluetoothGattDescriptor");
1201     if (!jni_cid_bluetoothGattDescriptor)
1202     {
1203         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattDescriptor is null");
1204         return CA_STATUS_FAILED;
1205     }
1206
1207     jmethodID jni_mid_bluetoothGattDescriptor = (*env)->GetMethodID(env,
1208                                                                     jni_cid_bluetoothGattDescriptor,
1209                                                                     "<init>",
1210                                                                     "(Ljava/util/UUID;I)V");
1211     if (!jni_mid_bluetoothGattDescriptor)
1212     {
1213         OIC_LOG(ERROR, TAG, "jni_mid_bluetoothGattDescriptor is null");
1214         return CA_STATUS_FAILED;
1215     }
1216
1217     jfieldID jni_fid_readPermissions = (*env)->GetStaticFieldID(env,
1218                                                                 jni_cid_bluetoothGattDescriptor,
1219                                                                 "PERMISSION_READ", "I");
1220     if (!jni_fid_readPermissions)
1221     {
1222         OIC_LOG(ERROR, TAG, "jni_fid_readPermissions is null");
1223         return CA_STATUS_FAILED;
1224     }
1225
1226     jobject jni_obj_readUuid = CALEGetUuidFromString(env, OIC_GATT_CHARACTERISTIC_CONFIG_UUID);
1227     if (!jni_obj_readUuid)
1228     {
1229         OIC_LOG(ERROR, TAG, "jni_obj_readUuid is null");
1230         return CA_STATUS_FAILED;
1231     }
1232
1233     jint jni_int_readPermissions = (*env)->GetStaticIntField(env, jni_cid_bluetoothGattDescriptor,
1234                                                              jni_fid_readPermissions);
1235
1236     OIC_LOG(DEBUG, TAG, "initialize new Descriptor");
1237
1238     jobject jni_readDescriptor = (*env)->NewObject(env, jni_cid_bluetoothGattDescriptor,
1239                                                    jni_mid_bluetoothGattDescriptor,
1240                                                    jni_obj_readUuid, jni_int_readPermissions);
1241     if (!jni_readDescriptor)
1242     {
1243         OIC_LOG(ERROR, TAG, "jni_readDescriptor is null");
1244         return CA_STATUS_FAILED;
1245     }
1246
1247     jclass jni_cid_GattCharacteristic = (*env)->FindClass(env, "android/bluetooth/"
1248                                                           "BluetoothGattCharacteristic");
1249     if (!jni_cid_GattCharacteristic)
1250     {
1251         OIC_LOG(ERROR, TAG, "jni_cid_GattCharacteristic is null");
1252         return CA_STATUS_FAILED;
1253     }
1254
1255     jmethodID jni_mid_addDescriptor = (*env)->GetMethodID(env, jni_cid_GattCharacteristic,
1256                                                           "addDescriptor",
1257                                                           "(Landroid/bluetooth/"
1258                                                           "BluetoothGattDescriptor;)Z");
1259     if (!jni_mid_addDescriptor)
1260     {
1261         OIC_LOG(ERROR, TAG, "jni_mid_addDescriptor is null");
1262         return CA_STATUS_FAILED;
1263     }
1264
1265     jboolean jni_boolean_addDescriptor = (*env)->CallBooleanMethod(env, characteristic,
1266                                                                    jni_mid_addDescriptor,
1267                                                                    jni_readDescriptor);
1268
1269     if (JNI_FALSE == jni_boolean_addDescriptor)
1270     {
1271         OIC_LOG(ERROR, TAG, "addDescriptor has failed");
1272         return CA_STATUS_FAILED;
1273     }
1274     else
1275     {
1276         OIC_LOG(DEBUG, TAG, "addDescriptor success");
1277     }
1278     return CA_STATUS_OK;
1279 }
1280
1281 CAResult_t CALEServerAddGattService(JNIEnv *env, jobject bluetoothGattServer,
1282                                           jobject bluetoothGattService)
1283 {
1284     OIC_LOG(DEBUG, TAG, "IN - CALEServerAddGattService");
1285     VERIFY_NON_NULL(env, TAG, "env is null");
1286     VERIFY_NON_NULL(bluetoothGattServer, TAG, "bluetoothGattServer is null");
1287     VERIFY_NON_NULL(bluetoothGattService, TAG, "bluetoothGattService is null");
1288
1289     if (!CALEIsEnableBTAdapter(env))
1290     {
1291         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1292         return CA_ADAPTER_NOT_ENABLED;
1293     }
1294
1295     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
1296                                                            "android/bluetooth/BluetoothGattServer");
1297     if (!jni_cid_bluetoothGattServer)
1298     {
1299         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null");
1300         return CA_STATUS_FAILED;
1301     }
1302
1303     jmethodID jni_mid_addService = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
1304                                                        "addService",
1305                                                        "(Landroid/bluetooth/BluetoothGattService;)"
1306                                                        "Z");
1307     if (!jni_mid_addService)
1308     {
1309         OIC_LOG(ERROR, TAG, "jni_mid_addService is null");
1310         return CA_STATUS_FAILED;
1311     }
1312
1313     jboolean jni_boolean_addService = (*env)->CallBooleanMethod(env, bluetoothGattServer,
1314                                                                 jni_mid_addService,
1315                                                                 bluetoothGattService);
1316
1317     if (JNI_FALSE == jni_boolean_addService)
1318     {
1319         OIC_LOG(ERROR, TAG, "Fail to add GATT service");
1320         return CA_STATUS_FAILED;
1321     }
1322
1323     OIC_LOG(DEBUG, TAG, "OUT - CALEServerAddGattService");
1324     return CA_STATUS_OK;
1325 }
1326
1327 CAResult_t CALEServerConnect(JNIEnv *env, jobject bluetoothDevice)
1328 {
1329     OIC_LOG(DEBUG, TAG, "IN - CALEServerConnect");
1330     VERIFY_NON_NULL(env, TAG, "env is null");
1331     VERIFY_NON_NULL(bluetoothDevice, TAG, "bluetoothDevice is null");
1332
1333     if (!CALEIsEnableBTAdapter(env))
1334     {
1335         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1336         return CA_ADAPTER_NOT_ENABLED;
1337     }
1338
1339     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
1340                                                            "android/bluetooth/BluetoothGattServer");
1341     if (!jni_cid_bluetoothGattServer)
1342     {
1343         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null");
1344         return CA_STATUS_FAILED;
1345     }
1346
1347     jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer, "connect",
1348                                                     "(Landroid/bluetooth/BluetoothDevice;Z)Z");
1349     if (!jni_mid_connect)
1350     {
1351         OIC_LOG(ERROR, TAG, "jni_mid_connect is null");
1352         return CA_STATUS_FAILED;
1353     }
1354
1355     jboolean jni_boolean_connect = (*env)->CallBooleanMethod(env, g_bluetoothGattServer,
1356                                                              jni_mid_connect, bluetoothDevice,
1357                                                              JNI_FALSE);
1358     if (JNI_FALSE == jni_boolean_connect)
1359     {
1360         OIC_LOG(ERROR, TAG, "Fail to connect");
1361         return CA_STATUS_FAILED;
1362     }
1363
1364     OIC_LOG(DEBUG, TAG, "OUT - CALEServerConnect");
1365     return CA_STATUS_OK;
1366 }
1367
1368 CAResult_t CALEServerDisconnectAllDevices(JNIEnv *env)
1369 {
1370     OIC_LOG(DEBUG, TAG, "IN - CALEServerDisconnectAllDevices");
1371     VERIFY_NON_NULL(env, TAG, "env is null");
1372
1373     ca_mutex_lock(g_connectedDeviceListMutex);
1374     if (!g_connectedDeviceList)
1375     {
1376         OIC_LOG(ERROR, TAG, "g_connectedDeviceList is null");
1377         ca_mutex_unlock(g_connectedDeviceListMutex);
1378         return CA_STATUS_FAILED;
1379     }
1380
1381     uint32_t length = u_arraylist_length(g_connectedDeviceList);
1382     for (uint32_t index = 0; index < length; index++)
1383     {
1384         jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
1385         if (!jarrayObj)
1386         {
1387             OIC_LOG_V(ERROR, TAG, "object[%d] is null", index);
1388             continue;
1389         }
1390
1391         // disconnect for device obj
1392         CAResult_t res = CALEServerDisconnect(env, jarrayObj);
1393         if (CA_STATUS_OK != res)
1394         {
1395             OIC_LOG_V(ERROR, TAG, "Disconnect for this device[%d] has failed", index);
1396             continue;
1397         }
1398     }
1399
1400     ca_mutex_unlock(g_connectedDeviceListMutex);
1401     OIC_LOG(DEBUG, TAG, "OUT - CALEServerDisconnectAllDevices");
1402     return CA_STATUS_OK;
1403 }
1404
1405 CAResult_t CALEServerDisconnect(JNIEnv *env, jobject bluetoothDevice)
1406 {
1407     OIC_LOG(DEBUG, TAG, "IN - CALEServerDisconnect");
1408     VERIFY_NON_NULL(env, TAG, "env is null");
1409     VERIFY_NON_NULL(bluetoothDevice, TAG, "bluetoothDevice is null");
1410
1411     if (!CALEIsEnableBTAdapter(env))
1412     {
1413         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1414         return CA_ADAPTER_NOT_ENABLED;
1415     }
1416
1417     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
1418                                                            "android/bluetooth/BluetoothGattServer");
1419     if (!jni_cid_bluetoothGattServer)
1420     {
1421         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null");
1422         return CA_STATUS_FAILED;
1423     }
1424
1425     jmethodID jni_mid_cancelConnection = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
1426                                                              "cancelConnection",
1427                                                              "(Landroid/bluetooth/BluetoothDevice;)"
1428                                                              "V");
1429     if (!jni_mid_cancelConnection)
1430     {
1431         OIC_LOG(ERROR, TAG, "jni_mid_cancelConnection is null");
1432         return CA_STATUS_FAILED;
1433     }
1434
1435     (*env)->CallVoidMethod(env, g_bluetoothGattServer, jni_mid_cancelConnection, bluetoothDevice);
1436
1437     if ((*env)->ExceptionCheck(env))
1438     {
1439         OIC_LOG(ERROR, TAG, "cancelConnection has failed");
1440         (*env)->ExceptionDescribe(env);
1441         (*env)->ExceptionClear(env);
1442         return CA_STATUS_FAILED;
1443     }
1444
1445     OIC_LOG(DEBUG, TAG, "OUT - CALEServerDisconnect");
1446     return CA_STATUS_OK;
1447 }
1448
1449 CAResult_t CALEServerGattClose(JNIEnv *env, jobject bluetoothGattServer)
1450 {
1451     // GATT CLOSE
1452     OIC_LOG(DEBUG, TAG, "GattServer Close");
1453     VERIFY_NON_NULL(bluetoothGattServer, TAG, "bluetoothGattServer is null");
1454     VERIFY_NON_NULL(env, TAG, "env is null");
1455
1456     // get BluetoothGatt class
1457     OIC_LOG(DEBUG, TAG, "get BluetoothGatt class");
1458     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, "android/bluetooth/BluetoothGattServer");
1459     if (!jni_cid_BluetoothGatt)
1460     {
1461         OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
1462         return CA_STATUS_FAILED;
1463     }
1464
1465     jmethodID jni_mid_closeGatt = (*env)->GetMethodID(env, jni_cid_BluetoothGatt, "close", "()V");
1466     if (!jni_mid_closeGatt)
1467     {
1468         OIC_LOG(ERROR, TAG, "jni_mid_closeGatt is null");
1469         return CA_STATUS_OK;
1470     }
1471
1472     // call disconnect gatt method
1473     OIC_LOG(DEBUG, TAG, "request to close GATT");
1474     (*env)->CallVoidMethod(env, bluetoothGattServer, jni_mid_closeGatt);
1475
1476     if ((*env)->ExceptionCheck(env))
1477     {
1478         OIC_LOG(ERROR, TAG, "closeGATT has failed");
1479         (*env)->ExceptionDescribe(env);
1480         (*env)->ExceptionClear(env);
1481         return CA_STATUS_FAILED;
1482     }
1483
1484     return CA_STATUS_OK;
1485 }
1486
1487 CAResult_t CALEServerSend(JNIEnv *env, jobject bluetoothDevice, jbyteArray responseData)
1488 {
1489     OIC_LOG(DEBUG, TAG, "IN - CALEServerSend");
1490     VERIFY_NON_NULL(env, TAG, "env is null");
1491     VERIFY_NON_NULL(bluetoothDevice, TAG, "bluetoothDevice is null");
1492     VERIFY_NON_NULL(responseData, TAG, "responseData is null");
1493
1494     if (!CALEIsEnableBTAdapter(env))
1495     {
1496         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1497         return CA_ADAPTER_NOT_ENABLED;
1498     }
1499
1500     jobject responseChar = CALEServerSetResponseData(env, responseData);
1501     if (!responseChar)
1502     {
1503         OIC_LOG(ERROR, TAG, "responseChar is null");
1504         return CA_STATUS_FAILED;
1505     }
1506
1507     CAResult_t result = CALEServerSendResponseData(env, bluetoothDevice, responseChar);
1508     if (CA_STATUS_OK != result)
1509     {
1510         OIC_LOG(ERROR, TAG, "Fail to send response data");
1511         return result;
1512     }
1513
1514     OIC_LOG(DEBUG, TAG, "OUT - CALEServerSend");
1515     return result;
1516 }
1517
1518 CAResult_t CALEServerInitialize()
1519 {
1520     OIC_LOG(DEBUG, TAG, "IN - CALEServerInitialize");
1521
1522     CALeServerJniInit();
1523
1524     if (!g_jvm)
1525     {
1526         OIC_LOG(ERROR, TAG, "g_jvm is null");
1527         return CA_STATUS_FAILED;
1528     }
1529
1530     bool isAttached = false;
1531     JNIEnv* env;
1532     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1533     if (JNI_OK != res)
1534     {
1535         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1536         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1537
1538         if (JNI_OK != res)
1539         {
1540             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1541             return CA_STATUS_FAILED;
1542         }
1543         isAttached = true;
1544     }
1545
1546     CAResult_t ret = CALECheckPlatformVersion(env, 21);
1547     if (CA_STATUS_OK != ret)
1548     {
1549         OIC_LOG(ERROR, TAG, "it is not supported");
1550
1551         if (isAttached)
1552         {
1553             (*g_jvm)->DetachCurrentThread(g_jvm);
1554         }
1555         return ret;
1556     }
1557
1558     g_threadSendNotifyCond = ca_cond_new();
1559
1560     ret = CALEServerInitMutexVaraibles();
1561     if (CA_STATUS_OK != ret)
1562     {
1563         OIC_LOG(ERROR, TAG, "CALEServerInitMutexVaraibles has failed");
1564
1565         if (isAttached)
1566         {
1567             (*g_jvm)->DetachCurrentThread(g_jvm);
1568         }
1569         return CA_STATUS_FAILED;
1570     }
1571
1572     CALEServerJNISetContext();
1573     CALEServerCreateCachedDeviceList();
1574
1575     ret = CALEServerCreateJniInterfaceObject();
1576     if (CA_STATUS_OK != ret)
1577     {
1578         OIC_LOG(ERROR, TAG, "CALEServerCreateJniInterfaceObject has failed");
1579
1580         if (isAttached)
1581         {
1582             (*g_jvm)->DetachCurrentThread(g_jvm);
1583         }
1584         return CA_STATUS_FAILED;
1585     }
1586
1587     if (isAttached)
1588     {
1589         (*g_jvm)->DetachCurrentThread(g_jvm);
1590     }
1591
1592     g_isInitializedServer = true;
1593     OIC_LOG(DEBUG, TAG, "OUT - CALEServerInitialize");
1594     return CA_STATUS_OK;
1595 }
1596
1597 void CALEServerTerminate()
1598 {
1599     OIC_LOG(DEBUG, TAG, "IN - CALEServerTerminate");
1600
1601     if (!g_jvm)
1602     {
1603         OIC_LOG(ERROR, TAG, "g_jvm is null");
1604         return;
1605     }
1606
1607     bool isAttached = false;
1608     JNIEnv* env;
1609     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1610     if (JNI_OK != res)
1611     {
1612         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1613         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1614
1615         if (JNI_OK != res)
1616         {
1617             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1618             return;
1619         }
1620         isAttached = true;
1621     }
1622
1623     if (g_sendBuffer)
1624     {
1625         (*env)->DeleteGlobalRef(env, g_sendBuffer);
1626         g_sendBuffer = NULL;
1627     }
1628
1629     if (g_bluetoothManager)
1630     {
1631         (*env)->DeleteGlobalRef(env, g_bluetoothManager);
1632         g_bluetoothManager = NULL;
1633     }
1634
1635     ca_cond_free(g_threadSendNotifyCond);
1636     g_threadSendNotifyCond = NULL;
1637
1638     CALEServerTerminateMutexVaraibles();
1639     CALEServerTerminateConditionVaraibles();
1640
1641     g_isInitializedServer = false;
1642
1643     if (isAttached)
1644     {
1645         (*g_jvm)->DetachCurrentThread(g_jvm);
1646     }
1647
1648     OIC_LOG(DEBUG, TAG, "OUT - CALEServerTerminate");
1649 }
1650
1651 CAResult_t CALEServerSendUnicastMessage(const char* address, const uint8_t* data, uint32_t dataLen)
1652 {
1653     OIC_LOG_V(DEBUG, TAG, "CALEServerSendUnicastMessage(%s, %p)", address, data);
1654     VERIFY_NON_NULL(address, TAG, "address is null");
1655     VERIFY_NON_NULL(data, TAG, "data is null");
1656
1657     if (!g_jvm)
1658     {
1659         OIC_LOG(ERROR, TAG, "g_jvm is null");
1660         return CA_STATUS_FAILED;
1661     }
1662
1663     bool isAttached = false;
1664     JNIEnv* env;
1665     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1666     if (JNI_OK != res)
1667     {
1668         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1669         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1670
1671         if (JNI_OK != res)
1672         {
1673             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1674             return CA_STATUS_FAILED;
1675         }
1676         isAttached = true;
1677     }
1678
1679     CAResult_t ret = CALEServerSendUnicastMessageImpl(env, address, data, dataLen);
1680     if (CA_STATUS_OK != ret)
1681     {
1682         OIC_LOG(ERROR, TAG, "CALEServerSendUnicastMessageImpl has failed");
1683     }
1684
1685     if (isAttached)
1686     {
1687         (*g_jvm)->DetachCurrentThread(g_jvm);
1688     }
1689
1690     return ret;
1691 }
1692
1693 CAResult_t CALEServerSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
1694 {
1695     OIC_LOG_V(DEBUG, TAG, "CALEServerSendMulticastMessage(%p)", data);
1696     VERIFY_NON_NULL(data, TAG, "data is null");
1697
1698     if (!g_jvm)
1699     {
1700         OIC_LOG(ERROR, TAG, "g_jvm is null");
1701         return CA_STATUS_FAILED;
1702     }
1703
1704     bool isAttached = false;
1705     JNIEnv* env;
1706     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1707     if (JNI_OK != res)
1708     {
1709         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1710         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1711
1712         if (JNI_OK != res)
1713         {
1714             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1715             return CA_STATUS_FAILED;
1716         }
1717         isAttached = true;
1718     }
1719
1720     CAResult_t ret = CALEServerSendMulticastMessageImpl(env, data, dataLen);
1721     if (CA_STATUS_OK != ret)
1722     {
1723         OIC_LOG(ERROR, TAG, "CALEServerSendMulticastMessageImpl has failed");
1724     }
1725
1726     if (isAttached)
1727     {
1728         (*g_jvm)->DetachCurrentThread(g_jvm);
1729     }
1730
1731     return ret;
1732 }
1733
1734 CAResult_t CALEServerStartMulticastServer()
1735 {
1736     OIC_LOG(DEBUG, TAG, "IN - CALEServerStartMulticastServer");
1737
1738     if (!g_isInitializedServer)
1739     {
1740         OIC_LOG(INFO, TAG, "server is not initialized");
1741         return CA_STATUS_FAILED;
1742     }
1743
1744     if (g_isStartServer)
1745     {
1746         OIC_LOG(INFO, TAG, "server is already started..it will be skipped");
1747         return CA_STATUS_FAILED;
1748     }
1749
1750     if (!g_jvm)
1751     {
1752         OIC_LOG(ERROR, TAG, "g_jvm is null");
1753         return CA_STATUS_FAILED;
1754     }
1755
1756     bool isAttached = false;
1757     JNIEnv* env;
1758     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1759     if (JNI_OK != res)
1760     {
1761         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1762         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1763
1764         if (JNI_OK != res)
1765         {
1766             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1767             return CA_STATUS_FAILED;
1768         }
1769         isAttached = true;
1770     }
1771
1772     g_isStartServer = true;
1773
1774     // start gatt server
1775     CAResult_t ret = CALEServerStartGattServer(env, g_bluetoothGattServerCallback);
1776     if (CA_STATUS_OK != ret)
1777     {
1778         OIC_LOG(ERROR, TAG, "Fail to start gatt server");
1779         return ret;
1780     }
1781
1782     // start advertise
1783     ret = CALEServerStartAdvertise(env, g_leAdvertiseCallback);
1784     if (CA_STATUS_OK != ret)
1785     {
1786         OIC_LOG(ERROR, TAG, "CALEServerStartAdvertise has failed");
1787     }
1788
1789     if (isAttached)
1790     {
1791         (*g_jvm)->DetachCurrentThread(g_jvm);
1792     }
1793
1794     OIC_LOG(DEBUG, TAG, "OUT - CALEServerStartMulticastServer");
1795     return ret;
1796 }
1797
1798 CAResult_t CALEServerStopMulticastServer()
1799 {
1800     OIC_LOG(DEBUG, TAG, "IN - CALEServerStopMulticastServer");
1801
1802     if (false == g_isStartServer)
1803     {
1804         OIC_LOG(INFO, TAG, "server is already stopped..it will be skipped");
1805         return CA_STATUS_FAILED;
1806     }
1807
1808     if (!g_jvm)
1809     {
1810         OIC_LOG(ERROR, TAG, "g_jvm is null");
1811         return CA_STATUS_FAILED;
1812     }
1813
1814     bool isAttached = false;
1815     JNIEnv* env;
1816     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1817     if (JNI_OK != res)
1818     {
1819         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1820         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1821
1822         if (JNI_OK != res)
1823         {
1824             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1825             return CA_STATUS_FAILED;
1826         }
1827         isAttached = true;
1828     }
1829
1830     CAResult_t ret = CALEServerStopAdvertise(env, g_leAdvertiseCallback);
1831     if (CA_STATUS_OK != ret)
1832     {
1833         OIC_LOG(ERROR, TAG, "CALEServerStopAdvertise has failed");
1834     }
1835
1836     g_isStartServer = false;
1837
1838     if (isAttached)
1839     {
1840         (*g_jvm)->DetachCurrentThread(g_jvm);
1841     }
1842
1843     OIC_LOG(DEBUG, TAG, "OUT - CALEServerStopMulticastServer");
1844     return ret;
1845 }
1846
1847 void CALEServerSetCallback(CAPacketReceiveCallback callback)
1848 {
1849     OIC_LOG(DEBUG, TAG, "CALEServerSetCallback");
1850     g_packetReceiveCallback = callback;
1851 }
1852
1853 CAResult_t CALEServerSendUnicastMessageImpl(JNIEnv *env, const char* address, const uint8_t* data,
1854                                             uint32_t dataLen)
1855 {
1856     OIC_LOG_V(DEBUG, TAG, "CALEServerSendUnicastMessageImpl, address: %s, data: %p",
1857             address, data);
1858     VERIFY_NON_NULL(env, TAG, "env is null");
1859     VERIFY_NON_NULL(address, TAG, "address is null");
1860     VERIFY_NON_NULL(data, TAG, "data is null");
1861
1862     if (!g_connectedDeviceList)
1863     {
1864         OIC_LOG(ERROR, TAG, "g_connectedDeviceList is null");
1865         return CA_STATUS_FAILED;
1866     }
1867
1868     ca_mutex_lock(g_threadSendMutex);
1869
1870     uint32_t length = u_arraylist_length(g_connectedDeviceList);
1871     for (uint32_t index = 0; index < length; index++)
1872     {
1873         OIC_LOG(DEBUG, TAG, "check device address");
1874         jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
1875         if (!jarrayObj)
1876         {
1877             OIC_LOG(ERROR, TAG, "jarrayObj is null");
1878             goto error_exit;
1879         }
1880
1881         jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
1882         if (!jni_setAddress)
1883         {
1884             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
1885             goto error_exit;
1886         }
1887         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
1888         if (!setAddress)
1889         {
1890             OIC_LOG(ERROR, TAG, "setAddress is null");
1891             goto error_exit;
1892         }
1893
1894         OIC_LOG_V(DEBUG, TAG, "setAddress : %s", setAddress);
1895         OIC_LOG_V(DEBUG, TAG, "address : %s", address);
1896
1897         if (!strcmp(setAddress, address))
1898         {
1899             OIC_LOG(DEBUG, TAG, "found the device");
1900
1901             if (g_obj_bluetoothDevice)
1902             {
1903                 (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice);
1904                 g_obj_bluetoothDevice = NULL;
1905             }
1906
1907             if (jarrayObj)
1908             {
1909                 g_obj_bluetoothDevice = (*env)->NewGlobalRef(env, jarrayObj);
1910             }
1911             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1912             break;
1913         }
1914         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1915     }
1916
1917     if (g_obj_bluetoothDevice)
1918     {
1919         jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
1920         (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
1921         g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
1922
1923         CAResult_t res = CALEServerSend(env, g_obj_bluetoothDevice, g_sendBuffer);
1924         if (CA_STATUS_OK != res)
1925         {
1926             OIC_LOG(ERROR, TAG, "send has failed");
1927             goto error_exit;
1928         }
1929     }
1930     else
1931     {
1932         OIC_LOG(ERROR, TAG, "There are no device to send in the list");
1933         goto error_exit;
1934     }
1935
1936     if (g_sendBuffer)
1937     {
1938         (*env)->DeleteGlobalRef(env, g_sendBuffer);
1939         g_sendBuffer = NULL;
1940     }
1941
1942     ca_mutex_unlock(g_threadSendMutex);
1943     OIC_LOG(INFO, TAG, "unicast - send request is successful");
1944     return CA_STATUS_OK;
1945
1946 error_exit:
1947     if (g_sendBuffer)
1948     {
1949         (*env)->DeleteGlobalRef(env, g_sendBuffer);
1950         g_sendBuffer = NULL;
1951     }
1952
1953     if (g_obj_bluetoothDevice)
1954     {
1955         (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice);
1956         g_obj_bluetoothDevice = NULL;
1957     }
1958
1959     ca_mutex_unlock(g_threadSendMutex);
1960     return CA_SEND_FAILED;
1961 }
1962
1963 CAResult_t CALEServerSendMulticastMessageImpl(JNIEnv *env, const uint8_t *data, uint32_t dataLen)
1964 {
1965     OIC_LOG_V(DEBUG, TAG, "CALEServerSendMulticastMessageImpl, send to, data: %s", data);
1966     VERIFY_NON_NULL(env, TAG, "env is null");
1967     VERIFY_NON_NULL(data, TAG, "data is null");
1968
1969     if (!g_connectedDeviceList)
1970     {
1971         OIC_LOG(ERROR, TAG, "g_connectedDeviceList is null");
1972         return CA_STATUS_FAILED;
1973     }
1974
1975     ca_mutex_lock(g_threadSendMutex);
1976
1977     OIC_LOG(DEBUG, TAG, "set data into g_sendBuffer for notify");
1978     if (g_sendBuffer)
1979     {
1980         (*env)->DeleteGlobalRef(env, g_sendBuffer);
1981         g_sendBuffer = NULL;
1982     }
1983     jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
1984     (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
1985     g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
1986
1987     uint32_t length = u_arraylist_length(g_connectedDeviceList);
1988     for (uint32_t index = 0; index < length; index++)
1989     {
1990         jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
1991         if (!jarrayObj)
1992         {
1993             OIC_LOG(ERROR, TAG, "jarrayObj is null");
1994             continue;
1995         }
1996
1997         // send data for all device
1998         jbyteArray jni_bytearr_data = (*env)->NewByteArray(env, dataLen);
1999         (*env)->SetByteArrayRegion(env, jni_bytearr_data, 0, dataLen, (jbyte*) data);
2000
2001         jstring jni_address = CALEGetAddressFromBTDevice(env, jarrayObj);
2002         if (!jni_address)
2003         {
2004             OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
2005             continue;
2006         }
2007
2008         const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
2009         if (!address)
2010         {
2011             OIC_LOG(ERROR, TAG, "address is not available");
2012             continue;
2013         }
2014
2015         if (g_obj_bluetoothDevice)
2016         {
2017             (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice);
2018             g_obj_bluetoothDevice = NULL;
2019         }
2020
2021         if (jarrayObj)
2022         {
2023             g_obj_bluetoothDevice = (*env)->NewGlobalRef(env, jarrayObj);
2024         }
2025
2026         CAResult_t res = CALEServerSend(env, g_obj_bluetoothDevice, jni_bytearr_data);
2027         if (CA_STATUS_OK != res)
2028         {
2029             OIC_LOG_V(ERROR, TAG, "send has failed for the device[%s]", address);
2030             (*env)->ReleaseStringUTFChars(env, jni_address, address);
2031             if (g_obj_bluetoothDevice)
2032             {
2033                 (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice);
2034                 g_obj_bluetoothDevice = NULL;
2035             }
2036             continue;
2037         }
2038
2039         OIC_LOG_V(INFO, TAG, "unicast - send request is successful for a device[%s]", address);
2040         (*env)->ReleaseStringUTFChars(env, jni_address, address);
2041     }
2042
2043     if (g_sendBuffer)
2044     {
2045         (*env)->DeleteGlobalRef(env, g_sendBuffer);
2046         g_sendBuffer = NULL;
2047     }
2048
2049     ca_mutex_unlock(g_threadSendMutex);
2050     return CA_STATUS_OK;
2051 }
2052
2053 void CALEServerCreateCachedDeviceList()
2054 {
2055     ca_mutex_lock(g_connectedDeviceListMutex);
2056     // create new object array
2057     if (!g_connectedDeviceList)
2058     {
2059         OIC_LOG(DEBUG, TAG, "Create device list");
2060         g_connectedDeviceList = u_arraylist_create();
2061     }
2062     ca_mutex_unlock(g_connectedDeviceListMutex);
2063 }
2064
2065 bool CALEServerIsDeviceInList(JNIEnv *env, const char* remoteAddress)
2066 {
2067     VERIFY_NON_NULL_RET(env, TAG, "env is null", false);
2068     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
2069
2070     if (!g_connectedDeviceList)
2071     {
2072         OIC_LOG(ERROR, TAG, "list is null");
2073         return false;
2074     }
2075
2076     uint32_t length = u_arraylist_length(g_connectedDeviceList);
2077     for (uint32_t index = 0; index < length; index++)
2078     {
2079         jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
2080
2081         if (!jarrayObj)
2082         {
2083             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2084             return false;
2085         }
2086
2087         jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2088         if (!jni_setAddress)
2089         {
2090             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2091             return false;
2092         }
2093
2094         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2095         if (!setAddress)
2096         {
2097             OIC_LOG(ERROR, TAG, "setAddress is null");
2098             return false;
2099         }
2100
2101         if (!strcmp(remoteAddress, setAddress))
2102         {
2103             OIC_LOG(ERROR, TAG, "the device is already set");
2104             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2105             return true;
2106         }
2107         else
2108         {
2109             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2110             continue;
2111         }
2112     }
2113
2114     OIC_LOG(DEBUG, TAG, "there are no device in the list");
2115     return false;
2116 }
2117
2118 CAResult_t CALEServerAddDeviceToList(JNIEnv *env, jobject device)
2119 {
2120     OIC_LOG(DEBUG, TAG, "IN - CALEServerAddDeviceToList");
2121     VERIFY_NON_NULL(device, TAG, "device is null");
2122     VERIFY_NON_NULL(env, TAG, "env is null");
2123
2124     ca_mutex_lock(g_connectedDeviceListMutex);
2125
2126     if (!g_connectedDeviceList)
2127     {
2128         OIC_LOG(ERROR, TAG, "list is null");
2129         ca_mutex_unlock(g_connectedDeviceListMutex);
2130         return CA_STATUS_FAILED;
2131     }
2132
2133     jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
2134     if (!jni_remoteAddress)
2135     {
2136         OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2137         ca_mutex_unlock(g_connectedDeviceListMutex);
2138         return CA_STATUS_FAILED;
2139     }
2140
2141     const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2142     if (!remoteAddress)
2143     {
2144         OIC_LOG(ERROR, TAG, "remoteAddress is null");
2145         ca_mutex_unlock(g_connectedDeviceListMutex);
2146         return CA_STATUS_FAILED;
2147     }
2148
2149     if (false == CALEServerIsDeviceInList(env, remoteAddress))
2150     {
2151         jobject jni_obj_device = (*env)->NewGlobalRef(env, device);
2152         u_arraylist_add(g_connectedDeviceList, jni_obj_device);
2153         OIC_LOG_V(DEBUG, TAG, "Set the object to ArrayList as Element : %s", remoteAddress);
2154     }
2155
2156     (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2157     ca_mutex_unlock(g_connectedDeviceListMutex);
2158     OIC_LOG(DEBUG, TAG, "OUT - CALEServerAddDeviceToList");
2159     return CA_STATUS_OK;
2160 }
2161
2162 CAResult_t CALEServerRemoveAllDevices(JNIEnv *env)
2163 {
2164     OIC_LOG(DEBUG, TAG, "IN - CALEServerRemoveAllDevices");
2165     VERIFY_NON_NULL(env, TAG, "env is null");
2166
2167     ca_mutex_lock(g_connectedDeviceListMutex);
2168     if (!g_connectedDeviceList)
2169     {
2170         OIC_LOG(ERROR, TAG, "g_connectedDeviceList is null");
2171         ca_mutex_unlock(g_connectedDeviceListMutex);
2172         return CA_STATUS_FAILED;
2173     }
2174
2175     uint32_t length = u_arraylist_length(g_connectedDeviceList);
2176     for (uint32_t index = 0; index < length; index++)
2177     {
2178         jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
2179         if (jarrayObj)
2180         {
2181             (*env)->DeleteGlobalRef(env, jarrayObj);
2182         }
2183     }
2184
2185     OICFree(g_connectedDeviceList);
2186     g_connectedDeviceList = NULL;
2187     ca_mutex_unlock(g_connectedDeviceListMutex);
2188
2189     OIC_LOG(DEBUG, TAG, "OUT - CALEServerRemoveAllDevices");
2190     return CA_STATUS_OK;
2191 }
2192
2193 CAResult_t CALEServerRemoveDevice(JNIEnv *env, jstring address)
2194 {
2195     OIC_LOG(DEBUG, TAG, "IN CALEServerRemoveDevice");
2196     VERIFY_NON_NULL(env, TAG, "env is null");
2197     VERIFY_NON_NULL(address, TAG, "address is null");
2198
2199     ca_mutex_lock(g_connectedDeviceListMutex);
2200     if (!g_connectedDeviceList)
2201     {
2202         OIC_LOG(ERROR, TAG, "no deviceList");
2203         ca_mutex_unlock(g_connectedDeviceListMutex);
2204         return CA_STATUS_FAILED;
2205     }
2206
2207     uint32_t length = u_arraylist_length(g_connectedDeviceList);
2208     for (uint32_t index = 0; index < length; index++)
2209     {
2210         jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
2211
2212         if (jarrayObj)
2213         {
2214             jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2215             if (!jni_setAddress)
2216             {
2217                 OIC_LOG(ERROR, TAG, "wrong device address");
2218                 continue;
2219             }
2220             const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2221             if (!setAddress)
2222             {
2223                 OIC_LOG(ERROR, TAG, "setAddress is null");
2224                 continue;
2225             }
2226
2227             const char* remoteAddress = (*env)->GetStringUTFChars(env, address, NULL);
2228             if (!remoteAddress)
2229             {
2230                 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2231                 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2232                 continue;
2233             }
2234
2235             if (!strcmp(setAddress, remoteAddress))
2236             {
2237                 OIC_LOG_V(DEBUG, TAG, "device address : %s", remoteAddress);
2238
2239                 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2240                 (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2241                 (*env)->DeleteGlobalRef(env, jarrayObj);
2242                 jarrayObj = NULL;
2243
2244                 if (NULL == u_arraylist_remove(g_connectedDeviceList, index))
2245                 {
2246                     OIC_LOG(ERROR, TAG, "List removal failed.");
2247                     ca_mutex_unlock(g_connectedDeviceListMutex);
2248                     return CA_STATUS_FAILED;
2249                 }
2250                 ca_mutex_unlock(g_connectedDeviceListMutex);
2251                 return CA_STATUS_OK;
2252             }
2253             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2254             (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2255         }
2256     }
2257
2258     ca_mutex_unlock(g_connectedDeviceListMutex);
2259
2260     OIC_LOG(DEBUG, TAG, "there are no device in the device list");
2261
2262     OIC_LOG(DEBUG, TAG, "IN CALEServerRemoveDevice");
2263     return CA_STATUS_FAILED;
2264 }
2265
2266 JNIEXPORT void JNICALL
2267 Java_org_iotivity_ca_CaLeServerInterface_caLeRegisterGattServerCallback(JNIEnv *env, jobject obj,
2268                                                                         jobject callback)
2269 {
2270     OIC_LOG(DEBUG, TAG, "Register Le Gatt Server Callback");
2271     VERIFY_NON_NULL_VOID(env, TAG, "env");
2272     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2273     VERIFY_NON_NULL_VOID(callback, TAG, "callback");
2274
2275     g_bluetoothGattServerCallback = (*env)->NewGlobalRef(env, callback);
2276 }
2277
2278 JNIEXPORT void JNICALL
2279 Java_org_iotivity_ca_CaLeServerInterface_caLeRegisterBluetoothLeAdvertiseCallback(JNIEnv *env,
2280                                                                                   jobject obj,
2281                                                                                   jobject callback)
2282 {
2283     OIC_LOG(DEBUG, TAG, "Register Le Advertise Callback");
2284     VERIFY_NON_NULL_VOID(env, TAG, "env");
2285     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2286     VERIFY_NON_NULL_VOID(callback, TAG, "callback");
2287
2288     g_leAdvertiseCallback = (*env)->NewGlobalRef(env, callback);
2289 }
2290
2291 JNIEXPORT void JNICALL
2292 Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerConnectionStateChangeCallback(
2293         JNIEnv *env, jobject obj, jobject device, jint status, jint newState)
2294 {
2295     OIC_LOG(DEBUG, TAG, " Gatt Server ConnectionStateChange Callback");
2296     OIC_LOG_V(DEBUG, TAG, "New connection State: %d", newState);
2297
2298     VERIFY_NON_NULL_VOID(env, TAG, "env");
2299     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2300     VERIFY_NON_NULL_VOID(device, TAG, "device");
2301
2302     // STATE_CONNECTED
2303     jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
2304
2305     // STATE_DISCONNECTED
2306     jint state_disconnected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_DISCONNECTED");
2307
2308     if (newState == state_connected)
2309     {
2310
2311         OIC_LOG(DEBUG, TAG, "LE CONNECTED");
2312
2313         jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
2314         if (!jni_remoteAddress)
2315         {
2316             OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2317             return;
2318         }
2319
2320         const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2321         if (!remoteAddress)
2322         {
2323             OIC_LOG(ERROR, TAG, "remoteAddress is null");
2324             return;
2325         }
2326
2327         if (false == CALEServerIsDeviceInList(env, remoteAddress))
2328         {
2329             OIC_LOG(DEBUG, TAG, "add connected device to cache");
2330             CALEServerAddDeviceToList(env, device);
2331         }
2332         (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2333     }
2334     else if (newState == state_disconnected)
2335     {
2336         OIC_LOG(DEBUG, TAG, "LE DISCONNECTED");
2337
2338         jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
2339         CAResult_t ret = CALEServerRemoveDevice(env, jni_remoteAddress);
2340         if (CA_STATUS_OK != ret)
2341         {
2342             OIC_LOG(ERROR, TAG, "CALEServerRemoveDevice has failed");
2343         }
2344
2345         // start advertise
2346         ret = CALEServerStartAdvertise(env, g_leAdvertiseCallback);
2347         if (CA_STATUS_OK != ret)
2348         {
2349             OIC_LOG(ERROR, TAG, "CALEServerStartAdvertise has failed");
2350         }
2351     }
2352     else
2353     {
2354         OIC_LOG_V(DEBUG, TAG, "LE Connection state is [newState : %d, status %d]", newState,
2355                 status);
2356     }
2357 }
2358
2359 JNIEXPORT void JNICALL
2360 Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerServiceAddedCallback(JNIEnv *env,
2361                                                                             jobject obj,
2362                                                                             jint status,
2363                                                                             jobject gattService)
2364 {
2365     VERIFY_NON_NULL_VOID(env, TAG, "env");
2366     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2367     VERIFY_NON_NULL_VOID(gattService, TAG, "gattService");
2368
2369     OIC_LOG_V(DEBUG, TAG, "Gatt Service Added Callback(%d)", status);
2370 }
2371
2372 JNIEXPORT void JNICALL
2373 Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerCharacteristicReadRequestCallback(
2374         JNIEnv *env, jobject obj, jobject device, jbyteArray data)
2375 {
2376     OIC_LOG(DEBUG, TAG, " Gatt Server Characteristic Read Request Callback");
2377     VERIFY_NON_NULL_VOID(env, TAG, "env");
2378     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2379     VERIFY_NON_NULL_VOID(device, TAG, "device");
2380     VERIFY_NON_NULL_VOID(data, TAG, "data");
2381 }
2382
2383 JNIEXPORT void JNICALL
2384 Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerCharacteristicWriteRequestCallback(
2385         JNIEnv *env, jobject obj, jobject device, jbyteArray data)
2386 {
2387     OIC_LOG_V(DEBUG, TAG, "Gatt Server Characteristic Write Request Callback");
2388     VERIFY_NON_NULL_VOID(env, TAG, "env");
2389     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2390     VERIFY_NON_NULL_VOID(device, TAG, "device");
2391     VERIFY_NON_NULL_VOID(data, TAG, "data");
2392
2393     // get Byte Array and covert to uint8_t*
2394     jint length = (*env)->GetArrayLength(env, data);
2395
2396     jboolean isCopy;
2397     jbyte *jni_byte_requestData = (jbyte *) (*env)->GetByteArrayElements(env, data, &isCopy);
2398
2399     uint8_t* requestData = NULL;
2400     requestData = OICMalloc(length);
2401     if (!requestData)
2402     {
2403         OIC_LOG(ERROR, TAG, "requestData is null");
2404         return;
2405     }
2406
2407     memcpy(requestData, jni_byte_requestData, length);
2408     (*env)->ReleaseByteArrayElements(env, data, jni_byte_requestData, JNI_ABORT);
2409
2410     jstring jni_address = CALEGetAddressFromBTDevice(env, device);
2411     if (!jni_address)
2412     {
2413         OIC_LOG(ERROR, TAG, "jni_address is null");
2414         OICFree(requestData);
2415         return;
2416     }
2417
2418     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
2419     if (!address)
2420     {
2421         OIC_LOG(ERROR, TAG, "address is null");
2422         OICFree(requestData);
2423         return;
2424     }
2425
2426     OIC_LOG_V(DEBUG, TAG, "remote device address : %s, %p, %d", address, requestData, length);
2427
2428     ca_mutex_lock(g_bleClientBDAddressMutex);
2429     uint32_t sentLength = 0;
2430     g_CABLEServerDataReceivedCallback(address, requestData, length,
2431                                       &sentLength);
2432     ca_mutex_unlock(g_bleClientBDAddressMutex);
2433
2434     (*env)->ReleaseStringUTFChars(env, jni_address, address);
2435 }
2436
2437 JNIEXPORT void JNICALL
2438 Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerNotificationSentCallback(JNIEnv *env,
2439                                                                                 jobject obj,
2440                                                                                 jobject device,
2441                                                                                 jint status)
2442 {
2443     VERIFY_NON_NULL_VOID(env, TAG, "env");
2444     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2445     VERIFY_NON_NULL_VOID(device, TAG, "device");
2446
2447     OIC_LOG_V(DEBUG, TAG, "Gatt Server Notification Sent Callback (status : %d)",
2448               status);
2449
2450     jint gatt_success = CALEGetConstantsValue(env, CLASSPATH_BT_GATT, "GATT_SUCCESS");
2451     if (gatt_success != status) // error case
2452     {
2453         OIC_LOG(ERROR, TAG, "it will be sent again.");
2454
2455         CAResult_t res = CALEServerSend(env, device, g_sendBuffer);
2456         if (CA_STATUS_OK != res)
2457         {
2458             OIC_LOG(ERROR, TAG, "send has failed");
2459
2460             if (g_obj_bluetoothDevice)
2461             {
2462                 (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice);
2463                 g_obj_bluetoothDevice = NULL;
2464             }
2465
2466             ca_mutex_lock(g_threadSendNotifyMutex);
2467             g_isSignalSetFlag = true;
2468             ca_cond_signal(g_threadSendNotifyCond);
2469             ca_mutex_unlock(g_threadSendNotifyMutex);
2470             return;
2471         }
2472     }
2473     else
2474     {
2475         OIC_LOG(DEBUG, TAG, "notify success");
2476
2477         if (g_obj_bluetoothDevice)
2478         {
2479             (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice);
2480             g_obj_bluetoothDevice = NULL;
2481         }
2482
2483         // next data can be sent
2484         ca_mutex_lock(g_threadSendNotifyMutex);
2485         OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
2486         g_isSignalSetFlag = true;
2487         ca_cond_signal(g_threadSendNotifyCond);
2488         ca_mutex_unlock(g_threadSendNotifyMutex);
2489     }
2490
2491 }
2492
2493 JNIEXPORT void JNICALL
2494 Java_org_iotivity_ca_CaLeServerInterface_caLeAdvertiseStartSuccessCallback(JNIEnv *env,
2495                                                                            jobject obj,
2496                                                                            jobject settingsInEffect)
2497 {
2498     VERIFY_NON_NULL_VOID(env, TAG, "env");
2499     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2500     VERIFY_NON_NULL_VOID(settingsInEffect, TAG, "settingsInEffect");
2501
2502     OIC_LOG(DEBUG, TAG, "LE Advertise Start Success Callback");
2503 }
2504
2505 JNIEXPORT void JNICALL
2506 Java_org_iotivity_ca_CaLeServerInterface_caLeAdvertiseStartFailureCallback(JNIEnv *env,
2507                                                                            jobject obj,
2508                                                                            jint errorCode)
2509 {
2510     VERIFY_NON_NULL_VOID(env, TAG, "env");
2511     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2512
2513     OIC_LOG_V(INFO, TAG, "LE Advertise Start Failure Callback(%d)", errorCode);
2514
2515     jint data_too_large = CALEGetConstantsValue(env, CLASSPATH_BT_ADVERTISE_CB,
2516                                                 "ADVERTISE_FAILED_DATA_TOO_LARGE");
2517     if (data_too_large == errorCode)
2518     {
2519         OIC_LOG_V(ERROR, TAG, "advertise data too large. please check length of device name");
2520     }
2521 }
2522
2523 /**
2524  * adapter common
2525  */
2526
2527 CAResult_t CAStartLEGattServer()
2528 {
2529     // start gatt service
2530     CALEServerStartMulticastServer();
2531
2532     return CA_STATUS_OK;
2533 }
2534
2535 CAResult_t CAStopLEGattServer()
2536 {
2537     OIC_LOG(DEBUG, TAG, "CAStopLEGattServer");
2538
2539     if (!g_jvm)
2540     {
2541         OIC_LOG(ERROR, TAG, "g_jvm is null");
2542         return CA_STATUS_FAILED;
2543     }
2544
2545     bool isAttached = false;
2546     JNIEnv* env;
2547     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
2548     if (JNI_OK != res)
2549     {
2550         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
2551         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
2552
2553         if (JNI_OK != res)
2554         {
2555             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
2556             return CA_STATUS_FAILED;
2557         }
2558         isAttached = true;
2559     }
2560
2561     CAResult_t ret = CALEServerGattClose(env, g_bluetoothGattServer);
2562     if (CA_STATUS_OK != ret)
2563     {
2564         OIC_LOG(ERROR, TAG, "CALEServerGattClose has failed");
2565         return CA_STATUS_FAILED;
2566     }
2567
2568     ret = CALEServerStopMulticastServer();
2569     if (CA_STATUS_OK != ret)
2570     {
2571         OIC_LOG(ERROR, TAG, "CALEServerStopMulticastServer has failed");
2572         return CA_STATUS_FAILED;
2573     }
2574
2575     ret = CALEServerDisconnectAllDevices(env);
2576     if (CA_STATUS_OK != ret)
2577     {
2578         OIC_LOG(ERROR, TAG, "CALEServerDisconnectAllDevices has failed");
2579         return CA_STATUS_FAILED;
2580     }
2581
2582     ret = CALEServerRemoveAllDevices(env);
2583     if (CA_STATUS_OK != ret)
2584     {
2585         OIC_LOG(ERROR, TAG, "CALEServerRemoveAllDevices has failed");
2586         return CA_STATUS_FAILED;
2587     }
2588
2589     if (g_leAdvertiseCallback)
2590     {
2591         (*env)->DeleteGlobalRef(env, g_leAdvertiseCallback);
2592     }
2593
2594     if (g_bluetoothGattServer)
2595     {
2596         (*env)->DeleteGlobalRef(env, g_bluetoothGattServer);
2597     }
2598
2599     if (g_bluetoothGattServerCallback)
2600     {
2601         (*env)->DeleteGlobalRef(env, g_bluetoothGattServerCallback);
2602     }
2603
2604     if (g_obj_bluetoothDevice)
2605     {
2606         (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice);
2607         g_obj_bluetoothDevice = NULL;
2608     }
2609
2610     ca_mutex_lock(g_threadSendNotifyMutex);
2611     ca_cond_signal(g_threadSendNotifyCond);
2612     ca_mutex_unlock(g_threadSendNotifyMutex);
2613
2614     g_isStartServer = false;
2615
2616     if (isAttached)
2617     {
2618         (*g_jvm)->DetachCurrentThread(g_jvm);
2619     }
2620
2621     return CA_STATUS_OK;
2622 }
2623
2624 CAResult_t CAInitializeLEGattServer()
2625 {
2626     OIC_LOG(DEBUG, TAG, "Initialize Gatt Server");
2627     return CALEServerInitialize();
2628 }
2629
2630 void CATerminateLEGattServer()
2631 {
2632     OIC_LOG(DEBUG, TAG, "Terminate Gatt Server");
2633     CALEServerTerminate();
2634 }
2635
2636 void CASetLEReqRespServerCallback(CABLEDataReceivedCallback callback)
2637 {
2638     ca_mutex_lock(g_bleReqRespCbMutex);
2639     g_CABLEServerDataReceivedCallback = callback;
2640     ca_mutex_unlock(g_bleReqRespCbMutex);
2641 }
2642
2643 void CASetBLEServerErrorHandleCallback(CABLEErrorHandleCallback callback)
2644 {
2645     g_serverErrorCallback = callback;
2646 }
2647
2648 CAResult_t CAUpdateCharacteristicsToGattClient(const char *address,
2649                                                const uint8_t *charValue,
2650                                                uint32_t charValueLen)
2651 {
2652     CAResult_t result = CA_SEND_FAILED;
2653     VERIFY_NON_NULL(address, TAG, "env is null");
2654     VERIFY_NON_NULL(charValue, TAG, "device is null");
2655
2656     if (address)
2657     {
2658         result = CALEServerSendUnicastMessage(address, charValue, charValueLen);
2659     }
2660
2661     return result;
2662 }
2663
2664 CAResult_t CAUpdateCharacteristicsToAllGattClients(const uint8_t *charValue,
2665                                                    uint32_t charValueLen)
2666 {
2667     VERIFY_NON_NULL(charValue, TAG, "device is null");
2668
2669     CAResult_t result = CALEServerSendMulticastMessage(charValue, charValueLen);
2670
2671     return result;
2672 }
2673
2674 void CASetLEServerThreadPoolHandle(ca_thread_pool_t handle)
2675 {
2676     OIC_LOG(INFO, TAG, "CASetLEServerThreadPoolHandle is not support");
2677     (void)handle;
2678 }
2679
2680 CAResult_t CALEServerInitMutexVaraibles()
2681 {
2682     if (NULL == g_bleReqRespCbMutex)
2683     {
2684         g_bleReqRespCbMutex = ca_mutex_new();
2685         if (NULL == g_bleReqRespCbMutex)
2686         {
2687             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
2688             return CA_STATUS_FAILED;
2689         }
2690     }
2691
2692     if (NULL == g_bleClientBDAddressMutex)
2693     {
2694         g_bleClientBDAddressMutex = ca_mutex_new();
2695         if (NULL == g_bleClientBDAddressMutex)
2696         {
2697             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
2698             return CA_STATUS_FAILED;
2699         }
2700     }
2701
2702     if (NULL == g_connectedDeviceListMutex)
2703     {
2704         g_connectedDeviceListMutex = ca_mutex_new();
2705         if (NULL == g_connectedDeviceListMutex)
2706         {
2707             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
2708             return CA_STATUS_FAILED;
2709         }
2710     }
2711
2712     if (NULL == g_threadSendMutex)
2713     {
2714         g_threadSendMutex = ca_mutex_new();
2715         if (NULL == g_threadSendMutex)
2716         {
2717             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
2718             return CA_STATUS_FAILED;
2719         }
2720     }
2721
2722     if (NULL == g_threadSendNotifyMutex)
2723     {
2724         g_threadSendNotifyMutex = ca_mutex_new();
2725         if (NULL == g_threadSendNotifyMutex)
2726         {
2727             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
2728             return CA_STATUS_FAILED;
2729         }
2730     }
2731
2732     return CA_STATUS_OK;
2733 }
2734
2735 void CALEServerTerminateMutexVaraibles()
2736 {
2737     ca_mutex_free(g_bleReqRespCbMutex);
2738     g_bleReqRespCbMutex = NULL;
2739
2740     ca_mutex_free(g_bleClientBDAddressMutex);
2741     g_bleClientBDAddressMutex = NULL;
2742
2743     ca_mutex_free(g_connectedDeviceListMutex);
2744     g_connectedDeviceListMutex = NULL;
2745
2746     ca_mutex_free(g_threadSendMutex);
2747     g_threadSendMutex = NULL;
2748
2749     ca_mutex_free(g_threadSendNotifyMutex);
2750     g_threadSendNotifyMutex = NULL;
2751 }
2752
2753 void CALEServerTerminateConditionVaraibles()
2754 {
2755     OIC_LOG(DEBUG, TAG, "this method is not supported");
2756 }