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