1 /******************************************************************
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
24 #include <android/log.h>
26 #include "caleserver.h"
27 #include "caleutils.h"
29 #include "oic_malloc.h"
30 #include "uthreadpool.h"
31 #include "uarraylist.h"
32 #include "com_iotivity_jar_caleinterface.h"
34 #define TAG PCF("CA_LE_SERVER")
37 static const char OIC_GATT_SERVICE_UUID[] = "713d0000-503e-4c75-ba94-3148f18d941e";
39 static const char OIC_GATT_CHARACTERISTIC_RESPONSE_UUID[] = "713d0002-503e-4c75-ba94-3148f18d941e";
41 static const char OIC_GATT_CHARACTERISTIC_REQUEST_UUID[] = "713d0003-503e-4c75-ba94-3148f18d941e";
44 static jobject g_context;
45 static jobject g_bluetoothGattServer;
46 static jobject g_bluetoothGattServerCallback;
47 static jobject g_leAdvertiseCallback;
49 static CAPacketReceiveCallback g_packetReceiveCallback = NULL;
50 static u_arraylist_t *g_connectedDeviceList = NULL;
51 static u_thread_pool_t g_threadPoolHandle = NULL;
53 static jboolean g_isStartServer;
54 static jboolean g_isSendingMulticastData;
57 void CALEServerJNISetContext(JNIEnv *env, jobject context)
59 OIC_LOG(DEBUG, TAG, "CALEServerJNISetContext");
63 OIC_LOG(ERROR, TAG, "context is null");
66 g_context = (*env)->NewGlobalRef(env, context);
70 void CALeServerJniInit(JNIEnv *env, JavaVM *jvm)
72 OIC_LOG(DEBUG, TAG, "CALeServerJniInit");
76 jobject CANativeLEServerSetResponseData(JNIEnv *env, jbyteArray responseData)
78 if (!CALEIsEnableBTAdapter(env))
80 OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
84 OIC_LOG(DEBUG, TAG, "CALEServerSetResponseData");
86 jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
87 "android/bluetooth/BluetoothGattServer");
89 jclass jni_cid_bluetoothGattService = (*env)->FindClass(
90 env, "android/bluetooth/BluetoothGattService");
92 jclass jni_cid_bluetoothGattCharacteristic = (*env)->FindClass(
93 env, "android/bluetooth/BluetoothGattCharacteristic");
95 jmethodID jni_mid_getService = (*env)->GetMethodID(
96 env, jni_cid_bluetoothGattServer, "getService",
97 "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothGattService;");
99 jobject jni_obj_serviceUUID = CALEGetUuidFromString(env, OIC_GATT_SERVICE_UUID);
101 if (!g_bluetoothGattServer)
103 OIC_LOG(ERROR, TAG, "Check BluetoothGattServer status");
106 jobject jni_obj_bluetoothGattService = (*env)->CallObjectMethod(env, g_bluetoothGattServer,
108 jni_obj_serviceUUID);
110 jmethodID jni_mid_getCharacteristic = (*env)->GetMethodID(
111 env, jni_cid_bluetoothGattService, "getCharacteristic",
112 "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothGattCharacteristic;");
114 jobject jni_obj_responseUUID = CALEGetUuidFromString(env,
115 OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
117 jobject jni_obj_bluetoothGattCharacteristic = (*env)->CallObjectMethod(
118 env, jni_obj_bluetoothGattService, jni_mid_getCharacteristic, jni_obj_responseUUID);
120 jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_bluetoothGattCharacteristic,
121 "setValue", "([B)Z");
123 jboolean jni_boolean_setValue = (*env)->CallBooleanMethod(env,
124 jni_obj_bluetoothGattCharacteristic,
125 jni_mid_setValue, responseData);
127 if (jni_boolean_setValue == JNI_FALSE)
129 OIC_LOG(ERROR, TAG, "Fail to set response data");
132 return jni_obj_bluetoothGattCharacteristic;
135 CAResult_t CANativeLEServerSendResponseData(JNIEnv *env, jobject device, jobject responseData)
138 if (!CALEIsEnableBTAdapter(env))
140 OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
141 return CA_ADAPTER_NOT_ENABLED;
144 OIC_LOG(DEBUG, TAG, "CALEServerSendResponseData");
146 jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
147 "android/bluetooth/BluetoothGattServer");
149 jmethodID jni_mid_notifyCharacteristicChanged = (*env)->GetMethodID(
150 env, jni_cid_bluetoothGattServer, "notifyCharacteristicChanged",
151 "(Landroid/bluetooth/BluetoothDevice;"
152 "Landroid/bluetooth/BluetoothGattCharacteristic;Z)Z");
154 jboolean jni_boolean_notifyCharacteristicChanged = (*env)->CallBooleanMethod(
155 env, g_bluetoothGattServer, jni_mid_notifyCharacteristicChanged, device, responseData,
158 if (jni_boolean_notifyCharacteristicChanged == JNI_FALSE)
160 OIC_LOG(ERROR, TAG, "Fail to notify characteristic");
161 return CA_SEND_FAILED;
167 CAResult_t CANativeLEServerSendResponse(JNIEnv *env, jobject device, jint requestId, jint status,
168 jint offset, jbyteArray value)
171 if (!CALEIsEnableBTAdapter(env))
173 OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
174 return CA_ADAPTER_NOT_ENABLED;
177 OIC_LOG(DEBUG, TAG, "CALEServerSendResponse");
179 jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
180 "android/bluetooth/BluetoothGattServer");
182 jmethodID jni_mid_sendResponse = (*env)->GetMethodID(
183 env, jni_cid_bluetoothGattServer, "sendResponse",
184 "(Landroid/bluetooth/BluetoothDevice;III[B)Z");
186 jboolean jni_boolean_sendResponse = (*env)->CallBooleanMethod(env, g_bluetoothGattServer,
187 jni_mid_sendResponse, device,
188 requestId, status, offset, value);
190 if (jni_boolean_sendResponse == JNI_FALSE)
192 OIC_LOG(ERROR, TAG, "Fail to send response for gatt characteristic write request");
193 return CA_SEND_FAILED;
199 void CANativeLEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback)
202 OIC_LOG(DEBUG, TAG, "LEServerStartAdvertise");
204 if (!CALEIsEnableBTAdapter(env))
206 OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
210 jclass jni_cid_AdvertiseSettings = (*env)->FindClass(
211 env, "android/bluetooth/le/AdvertiseSettings$Builder");
213 jclass jni_cid_AdvertiseDataBuilder = (*env)->FindClass(
214 env, "android/bluetooth/le/AdvertiseData$Builder");
216 jclass jni_cid_BTAdapter = (*env)->FindClass(env, "android/bluetooth/BluetoothAdapter");
218 jclass jni_cid_leAdvertiser = (*env)->FindClass(env,
219 "android/bluetooth/le/BluetoothLeAdvertiser");
221 jmethodID jni_mid_AdvertiseSettings = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings,
224 jmethodID jni_mid_setAdvertiseMode = (*env)->GetMethodID(
225 env, jni_cid_AdvertiseSettings, "setAdvertiseMode",
226 "(I)Landroid/bluetooth/le/AdvertiseSettings$Builder;");
228 jmethodID jni_mid_setConnectable = (*env)->GetMethodID(
229 env, jni_cid_AdvertiseSettings, "setConnectable",
230 "(Z)Landroid/bluetooth/le/AdvertiseSettings$Builder;");
232 jmethodID jni_mid_setTimeout = (*env)->GetMethodID(
233 env, jni_cid_AdvertiseSettings, "setTimeout",
234 "(I)Landroid/bluetooth/le/AdvertiseSettings$Builder;");
236 jmethodID jni_mid_AdvertiseDataBuilder = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder,
239 jmethodID jni_mid_addServiceUuid = (*env)->GetMethodID(
240 env, jni_cid_AdvertiseDataBuilder, "addServiceUuid",
241 "(Landroid/os/ParcelUuid;)Landroid/bluetooth/le/AdvertiseData$Builder;");
243 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(
244 env, jni_cid_BTAdapter, "getDefaultAdapter", "()Landroid/bluetooth/BluetoothAdapter;");
246 jmethodID jni_mid_getBluetoothLeAdvertiser = (*env)->GetMethodID(
247 env, jni_cid_BTAdapter, "getBluetoothLeAdvertiser",
248 "()Landroid/bluetooth/le/BluetoothLeAdvertiser;");
250 jmethodID jni_mid_build_LeAdvertiseSettings = (*env)->GetMethodID(
251 env, jni_cid_AdvertiseSettings, "build", "()Landroid/bluetooth/le/AdvertiseSettings;");
253 jmethodID jni_mid_build_LeAdvertiseData = (*env)->GetMethodID(
254 env, jni_cid_AdvertiseDataBuilder, "build", "()Landroid/bluetooth/le/AdvertiseData;");
256 jmethodID jni_mid_startAdvertising = (*env)->GetMethodID(
257 env, jni_cid_leAdvertiser, "startAdvertising",
258 "(Landroid/bluetooth/le/AdvertiseSettings;Landroid/bluetooth/le/AdvertiseData;"
259 "Landroid/bluetooth/le/AdvertiseCallback;)V");
261 jobject jni_AdvertiseSettings = (*env)->NewObject(env, jni_cid_AdvertiseSettings,
262 jni_mid_AdvertiseSettings);
264 // 0: Low power, 1: Balanced
265 jobject jni_obj_setAdvertiseMode = (*env)->CallObjectMethod(env, jni_AdvertiseSettings,
266 jni_mid_setAdvertiseMode, 0);
268 jobject jni_obj_setConnectable = (*env)->CallObjectMethod(env, jni_AdvertiseSettings,
269 jni_mid_setConnectable, JNI_TRUE);
271 //A value of 0 will disable the time limit
272 jobject jni_obj_setTimeout = (*env)->CallObjectMethod(env, jni_AdvertiseSettings,
273 jni_mid_setTimeout, 0);
275 jobject jni_AdvertiseDataBuilder = (*env)->NewObject(env, jni_cid_AdvertiseDataBuilder,
276 jni_mid_AdvertiseDataBuilder);
278 jobject jni_obj_serviceUUID = CALEGetUuidFromString(env, OIC_GATT_SERVICE_UUID);
280 jobject jni_ParcelUuid = CALEGetParcelUuid(env, jni_obj_serviceUUID);
282 jobject jni_obj_addServiceUuid = (*env)->CallObjectMethod(env, jni_AdvertiseDataBuilder,
283 jni_mid_addServiceUuid,
286 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
287 jni_mid_getDefaultAdapter);
289 jobject jni_obj_getBluetoothLeAdvertiser = (*env)->CallObjectMethod(
290 env, jni_obj_BTAdapter, jni_mid_getBluetoothLeAdvertiser);
292 jobject jni_obj_build_LeAdvertiseSettings = (*env)->CallObjectMethod(
293 env, jni_AdvertiseSettings, jni_mid_build_LeAdvertiseSettings);
295 jobject jni_obj_build_LeAdvertiseData = (*env)->CallObjectMethod(env, jni_AdvertiseDataBuilder,
296 jni_mid_build_LeAdvertiseData);
298 (*env)->CallVoidMethod(env, jni_obj_getBluetoothLeAdvertiser, jni_mid_startAdvertising,
299 jni_obj_build_LeAdvertiseSettings, jni_obj_build_LeAdvertiseData,
302 OIC_LOG(DEBUG, TAG, "Advertising started!!");
305 void CANativeLEServerStopAdvertise(JNIEnv *env, jobject advertiseCallback)
308 OIC_LOG(DEBUG, TAG, "LEServerStopAdvertise");
310 if (!CALEIsEnableBTAdapter(env))
312 OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
316 jclass jni_cid_BTAdapter = (*env)->FindClass(env, "android/bluetooth/BluetoothAdapter");
318 jclass jni_cid_leAdvertiser = (*env)->FindClass(env,
319 "android/bluetooth/le/BluetoothLeAdvertiser");
321 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(
322 env, jni_cid_BTAdapter, "getDefaultAdapter", "()Landroid/bluetooth/BluetoothAdapter;");
324 jmethodID jni_mid_getBluetoothLeAdvertiser = (*env)->GetMethodID(
325 env, jni_cid_BTAdapter, "getBluetoothLeAdvertiser",
326 "()Landroid/bluetooth/le/BluetoothLeAdvertiser;");
328 jmethodID jni_mid_stopAdvertising = (*env)->GetMethodID(
329 env, jni_cid_leAdvertiser, "stopAdvertising",
330 "(Landroid/bluetooth/le/AdvertiseCallback;)V");
332 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
333 jni_mid_getDefaultAdapter);
335 jobject jni_obj_getBluetoothLeAdvertiser = (*env)->CallObjectMethod(
336 env, jni_obj_BTAdapter, jni_mid_getBluetoothLeAdvertiser);
338 (*env)->CallVoidMethod(env, jni_obj_getBluetoothLeAdvertiser, jni_mid_stopAdvertising,
341 OIC_LOG(DEBUG, TAG, "Advertising stopped!!");
344 CAResult_t CALEStartGattServer(JNIEnv *env, jobject gattServerCallback)
347 OIC_LOG(DEBUG, TAG, "CALEStartGattServer");
349 if (!CALEIsEnableBTAdapter(env))
351 OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
352 return CA_ADAPTER_NOT_ENABLED;
357 OIC_LOG(DEBUG, TAG, "Gatt server already started");
360 g_bluetoothGattServerCallback = (*env)->NewGlobalRef(env, gattServerCallback);
363 jobject bluetoothGattServer = CANativeLEServerOpenGattServer(env);
364 if (!bluetoothGattServer)
366 OIC_LOG(ERROR, TAG, "bluetoothGattServer is null");
367 return CA_STATUS_FAILED;
370 g_bluetoothGattServer = (*env)->NewGlobalRef(env, bluetoothGattServer);
372 // create gatt service
373 jobject bluetoothGattService = CANativeLEServerCreateGattService(env);
376 return CANativeLEServerAddGattService(env, g_bluetoothGattServer, bluetoothGattService);
379 jobject CANativeLEServerOpenGattServer(JNIEnv *env)
382 OIC_LOG(DEBUG, TAG, "CALEServerOpenGattServer");
384 if (!CALEIsEnableBTAdapter(env))
386 OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
390 jclass jni_cid_context = (*env)->FindClass(env, "android/content/Context");
392 jclass jni_cid_bluetoothManager = (*env)->FindClass(env, "android/bluetooth/BluetoothManager");
394 jfieldID jni_fid_bluetoothService = (*env)->GetStaticFieldID(env, jni_cid_context,
396 "Ljava/lang/String;");
398 jmethodID jni_mid_getSystemService = (*env)->GetMethodID(
399 env, jni_cid_context, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
401 jmethodID jni_mid_openGattServer = (*env)->GetMethodID(
402 env, jni_cid_bluetoothManager, "openGattServer",
403 "(Landroid/content/Context;Landroid/bluetooth/BluetoothGattServerCallback;)"
404 "Landroid/bluetooth/BluetoothGattServer;");
406 jobject jni_obj_bluetoothService = (*env)->GetStaticObjectField(env, jni_cid_context,
407 jni_fid_bluetoothService);
408 if (!jni_obj_bluetoothService)
410 OIC_LOG(ERROR, TAG, "jni_obj_bluetoothService is null");
414 jobject jni_obj_bluetoothManager = (*env)->CallObjectMethod(env, g_context,
415 jni_mid_getSystemService,
416 jni_obj_bluetoothService);
417 if (!jni_obj_bluetoothManager)
419 OIC_LOG(ERROR, TAG, "jni_obj_bluetoothManager is null");
423 jobject jni_obj_bluetoothGattServer = (*env)->CallObjectMethod(env, jni_obj_bluetoothManager,
424 jni_mid_openGattServer,
426 g_bluetoothGattServerCallback);
427 if (!jni_obj_bluetoothGattServer)
429 OIC_LOG(ERROR, TAG, "jni_obj_bluetoothGattServer is null");
433 return jni_obj_bluetoothGattServer;
436 jobject CANativeLEServerCreateGattService(JNIEnv *env)
439 OIC_LOG(DEBUG, TAG, "CALEServerCreateGattService");
441 if (!CALEIsEnableBTAdapter(env))
443 OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
447 jclass jni_cid_bluetoothGattService = (*env)->FindClass(
448 env, "android/bluetooth/BluetoothGattService");
450 jclass jni_cid_bluetoothGattCharacteristic = (*env)->FindClass(
451 env, "android/bluetooth/BluetoothGattCharacteristic");
453 jfieldID jni_fid_serviceType = (*env)->GetStaticFieldID(env, jni_cid_bluetoothGattService,
454 "SERVICE_TYPE_PRIMARY", "I");
456 jfieldID jni_fid_readProperties = (*env)->GetStaticFieldID(env,
457 jni_cid_bluetoothGattCharacteristic,
458 "PROPERTY_READ", "I");
460 jfieldID jni_fid_writeProperties = (*env)->GetStaticFieldID(env,
461 jni_cid_bluetoothGattCharacteristic,
462 "PROPERTY_WRITE", "I");
464 jfieldID jni_fid_readPermissions = (*env)->GetStaticFieldID(env,
465 jni_cid_bluetoothGattCharacteristic,
466 "PERMISSION_READ", "I");
468 jfieldID jni_fid_writePermissions = (*env)->GetStaticFieldID(
469 env, jni_cid_bluetoothGattCharacteristic, "PERMISSION_WRITE", "I");
471 jmethodID jni_mid_bluetoothGattService = (*env)->GetMethodID(env, jni_cid_bluetoothGattService,
472 "<init>", "(Ljava/util/UUID;I)V");
474 jmethodID jni_mid_addCharacteristic = (*env)->GetMethodID(
475 env, jni_cid_bluetoothGattService, "addCharacteristic",
476 "(Landroid/bluetooth/BluetoothGattCharacteristic;)Z");
478 jmethodID jni_mid_bluetoothGattCharacteristic = (*env)->GetMethodID(
479 env, jni_cid_bluetoothGattCharacteristic, "<init>", "(Ljava/util/UUID;II)V");
481 jobject jni_obj_serviceUUID = CALEGetUuidFromString(env, OIC_GATT_SERVICE_UUID);
483 jobject jni_obj_serviceType = (*env)->GetStaticObjectField(env, jni_cid_bluetoothGattService,
484 jni_fid_serviceType);
486 jobject jni_bluetoothGattService = (*env)->NewObject(env, jni_cid_bluetoothGattService,
487 jni_mid_bluetoothGattService,
488 jni_obj_serviceUUID, jni_obj_serviceType);
490 jobject jni_obj_readUuid = CALEGetUuidFromString(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
492 jint jni_int_readProperties = (*env)->GetStaticIntField(env,
493 jni_cid_bluetoothGattCharacteristic,
494 jni_fid_readProperties);
496 jint jni_int_readPermissions = (*env)->GetStaticIntField(env,
497 jni_cid_bluetoothGattCharacteristic,
498 jni_fid_readPermissions);
500 jobject jni_readCharacteristic = (*env)->NewObject(env, jni_cid_bluetoothGattCharacteristic,
501 jni_mid_bluetoothGattCharacteristic,
502 jni_obj_readUuid, jni_int_readProperties,
503 jni_int_readPermissions);
505 jboolean jni_boolean_addReadCharacteristic = (*env)->CallBooleanMethod(
506 env, jni_bluetoothGattService, jni_mid_addCharacteristic, jni_readCharacteristic);
508 jobject jni_obj_writeUuid = CALEGetUuidFromString(env, OIC_GATT_CHARACTERISTIC_REQUEST_UUID);
510 jint jni_int_writeProperties = (*env)->GetStaticIntField(env,
511 jni_cid_bluetoothGattCharacteristic,
512 jni_fid_writeProperties);
514 jint jni_int_writePermissions = (*env)->GetStaticIntField(env,
515 jni_cid_bluetoothGattCharacteristic,
516 jni_fid_writePermissions);
518 jobject jni_writeCharacteristic = (*env)->NewObject(env, jni_cid_bluetoothGattCharacteristic,
519 jni_mid_bluetoothGattCharacteristic,
520 jni_obj_writeUuid, jni_int_writeProperties,
521 jni_int_writePermissions);
523 jboolean jni_boolean_addWriteCharacteristic = (*env)->CallBooleanMethod(
524 env, jni_bluetoothGattService, jni_mid_addCharacteristic, jni_writeCharacteristic);
526 if (jni_boolean_addWriteCharacteristic == JNI_FALSE)
528 OIC_LOG(ERROR, TAG, "Fail to add jni_boolean_addReadCharacteristic");
532 return jni_bluetoothGattService;
535 CAResult_t CANativeLEServerAddGattService(JNIEnv *env, jobject bluetoothGattServer,
536 jobject bluetoothGattService)
539 OIC_LOG(DEBUG, TAG, "CALEServerAddGattService");
541 if (!CALEIsEnableBTAdapter(env))
543 OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
544 return CA_ADAPTER_NOT_ENABLED;
547 jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
548 "android/bluetooth/BluetoothGattServer");
550 jmethodID jni_mid_addService = (*env)->GetMethodID(
551 env, jni_cid_bluetoothGattServer, "addService",
552 "(Landroid/bluetooth/BluetoothGattService;)Z");
554 jboolean jni_boolean_addService = (*env)->CallBooleanMethod(env, bluetoothGattServer,
556 bluetoothGattService);
558 if (jni_boolean_addService == JNI_FALSE)
560 OIC_LOG(ERROR, TAG, "Fail to add gatt service");
561 return CA_STATUS_FAILED;
567 CAResult_t CANativeLEServerConnect(JNIEnv *env, jobject bluetoothDevice)
570 OIC_LOG(DEBUG, TAG, "CALEConnect");
572 if (!CALEIsEnableBTAdapter(env))
574 OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
575 return CA_ADAPTER_NOT_ENABLED;
578 jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
579 "android/bluetooth/BluetoothGattServer");
581 jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer, "connect",
582 "(Landroid/bluetooth/BluetoothDevice;Z)Z");
584 jboolean jni_boolean_connect = (*env)->CallBooleanMethod(env, g_bluetoothGattServer,
585 jni_mid_connect, bluetoothDevice,
588 if (jni_boolean_connect == JNI_FALSE)
590 OIC_LOG(ERROR, TAG, "Fail to connect");
591 return CA_STATUS_FAILED;
597 void CANativeLEServerDisconnect(JNIEnv *env, jobject bluetoothDevice)
600 OIC_LOG(DEBUG, TAG, "CALEDisconnect");
602 if (!CALEIsEnableBTAdapter(env))
604 OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
608 jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
609 "android/bluetooth/BluetoothGattServer");
611 jmethodID jni_mid_cancelConnection = (*env)->GetMethodID(
612 env, jni_cid_bluetoothGattServer, "cancelConnection",
613 "(Landroid/bluetooth/BluetoothDevice;)V");
615 (*env)->CallVoidMethod(env, g_bluetoothGattServer, jni_mid_cancelConnection, bluetoothDevice);
618 CAResult_t CALEServerSend(JNIEnv *env, jobject bluetoothDevice, jbyteArray responseData)
621 OIC_LOG(DEBUG, TAG, "CALESend");
623 if (!CALEIsEnableBTAdapter(env))
625 OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
626 return CA_ADAPTER_NOT_ENABLED;
629 jobject responseChar = CANativeLEServerSetResponseData(env, responseData);
631 CAResult_t result = CANativeLEServerSendResponseData(env, bluetoothDevice, responseChar);
633 if (result != CA_STATUS_OK)
635 OIC_LOG(ERROR, TAG, "Fail to send response data");
642 void CALeServerCreateJniInterfaceObject()
644 OIC_LOG(DEBUG, TAG, "CALeServerCreateJniInterfaceObject");
646 jboolean isAttached = JNI_FALSE;
648 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
651 OIC_LOG(DEBUG, TAG, "Could not get JNIEnv pointer");
652 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
656 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
659 isAttached = JNI_TRUE;
662 // initialize le server
666 (*g_jvm)->DetachCurrentThread(g_jvm);
670 void CALEServerInitialize(u_thread_pool_t handle)
672 OIC_LOG(DEBUG, TAG, "CALEServerInitialize");
674 g_threadPoolHandle = handle;
676 g_isSendingMulticastData = JNI_FALSE;
678 CALEServerCreateCachedDeviceList();
681 void CALEServerTerminate()
683 OIC_LOG(DEBUG, TAG, "CALEServerTerminate");
685 jboolean isAttached = JNI_FALSE;
687 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
690 OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
691 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
695 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
698 isAttached = JNI_TRUE;
701 CALEServerStopMulticastServer(0);
703 CALEServerRemoveAllDevices(env);
705 if (g_leAdvertiseCallback)
707 (*env)->DeleteGlobalRef(env, g_leAdvertiseCallback);
710 if (g_bluetoothGattServer)
712 (*env)->DeleteGlobalRef(env, g_bluetoothGattServer);
715 if (g_bluetoothGattServerCallback)
717 (*env)->DeleteGlobalRef(env, g_bluetoothGattServerCallback);
722 (*env)->DeleteGlobalRef(env, g_context);
725 g_isStartServer = JNI_FALSE;
729 (*g_jvm)->DetachCurrentThread(g_jvm);
733 CAResult_t CALEServerSendUnicastMessage(const char* address, const char* data, uint32_t dataLen)
735 OIC_LOG_V(DEBUG, TAG, "CALEServerSendUnicastMessage(%s, %s)", address, data);
737 jboolean isAttached = JNI_FALSE;
739 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
742 OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
743 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
747 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
748 return CA_STATUS_FAILED;
750 isAttached = JNI_TRUE;
753 CALEServerSendUnicastMessageImpl(env, address, data, dataLen);
757 (*g_jvm)->DetachCurrentThread(g_jvm);
763 CAResult_t CALEServerSendMulticastMessage(const char* data, uint32_t dataLen)
765 OIC_LOG_V(DEBUG, TAG, "CALEServerSendMulticastMessage(%s)", data);
767 jboolean isAttached = JNI_FALSE;
769 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
772 OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
773 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
777 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
778 return CA_STATUS_FAILED;
780 isAttached = JNI_TRUE;
783 CALEServerSendMulticastMessageImpl(env, data, dataLen);
787 (*g_jvm)->DetachCurrentThread(g_jvm);
793 CAResult_t CALEServerStartUnicastServer(const char* address)
795 OIC_LOG_V(DEBUG, TAG, "CALEServerStartUnicastServer(%s)", address);
800 CAResult_t CALEServerStartMulticastServer()
802 OIC_LOG(DEBUG, TAG, "CALEServerStartMulticastServer");
806 OIC_LOG(ERROR, TAG, "server is already started..it will be skipped");
807 return CA_STATUS_FAILED;
810 jboolean isAttached = JNI_FALSE;
812 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
815 OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
816 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
820 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
821 return CA_STATUS_FAILED;
823 isAttached = JNI_TRUE;
826 g_isStartServer = JNI_TRUE;
829 CAResult_t ret = CALEStartGattServer(env, g_bluetoothGattServerCallback);
830 if (CA_STATUS_OK != ret)
832 OIC_LOG(ERROR, TAG, "Fail to start gatt server");
837 CANativeLEServerStartAdvertise(env, g_leAdvertiseCallback);
841 (*g_jvm)->DetachCurrentThread(g_jvm);
847 CAResult_t CALEServerStopUnicastServer()
849 OIC_LOG(DEBUG, TAG, "CALEServerStopUnicastServer");
854 CAResult_t CALEServerStopMulticastServer()
856 OIC_LOG(DEBUG, TAG, "CALEServerStopMulticastServer");
858 if (g_isStartServer == JNI_FALSE)
860 OIC_LOG(ERROR, TAG, "server is already stopped..it will be skipped");
861 return CA_STATUS_FAILED;
864 jboolean isAttached = JNI_FALSE;
866 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
869 OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
870 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
874 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
875 return CA_STATUS_FAILED;
877 isAttached = JNI_TRUE;
880 CANativeLEServerStopAdvertise(env, g_leAdvertiseCallback);
882 g_isStartServer = JNI_FALSE;
886 (*g_jvm)->DetachCurrentThread(g_jvm);
892 void CALEServerSetCallback(CAPacketReceiveCallback callback)
894 OIC_LOG(DEBUG, TAG, "CALEServerSetCallback");
895 g_packetReceiveCallback = callback;
898 void CALEServerGetInterfaceInfo(CALocalConnectivity_t **info, uint32_t* size)
900 OIC_LOG(DEBUG, TAG, "CALEServerGetInterfaceInfo");
904 void CALEServerGetLocalAddress(char* address)
906 OIC_LOG(DEBUG, TAG, "CALEServerGetLocalAddress");
908 jboolean isAttached = JNI_FALSE;
910 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
913 OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
914 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
917 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
920 isAttached = JNI_TRUE;
923 jstring jni_address = CALEGetLocalDeviceAddress(env);
924 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
925 if (NULL == localAddress)
927 OIC_LOG(ERROR, TAG, "there are no local address");
931 memcpy(address, localAddress, strlen(localAddress));
933 OIC_LOG_V(DEBUG, TAG, "Local Address : %s", address);
936 (*g_jvm)->DetachCurrentThread(g_jvm);
940 CAResult_t CALEServerSendUnicastMessageImpl(JNIEnv *env, const char* address, const char* data,
943 OIC_LOG_V(DEBUG, TAG, "CALEServerSendUnicastMessageImpl, address: %s, data: %s", address, data);
945 // 1. get device object with address from cache
946 // 2. connect to the gatt client device
947 // 3. write a characteristic for response
951 jobject jni_obj_bluetoothDevice = NULL;
953 if (g_connectedDeviceList == NULL)
955 OIC_LOG(ERROR, TAG, "g_connectedDeviceList is null");
958 if (g_connectedDeviceList)
961 for (index = 0; index < u_arraylist_length(g_connectedDeviceList); index++)
963 OIC_LOG(DEBUG, TAG, "check device address");
964 jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
967 OIC_LOG(ERROR, TAG, "jarrayObj is null");
968 return CA_STATUS_FAILED;
971 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
974 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
975 return CA_STATUS_FAILED;
977 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
979 if (!strcmp(setAddress, address))
981 OIC_LOG(DEBUG, TAG, "device address matched");
982 jni_obj_bluetoothDevice = jarrayObj;
985 jni_obj_bluetoothDevice = jarrayObj;
988 if (jni_obj_bluetoothDevice)
990 jbyteArray jni_bytearr_data = (*env)->NewByteArray(env, dataLen);
991 (*env)->SetByteArrayRegion(env, jni_bytearr_data, 0, dataLen, (jbyte*) data);
993 CALEServerSend(env, jni_obj_bluetoothDevice, jni_bytearr_data);
998 OIC_LOG(ERROR, TAG, "jni_obj_bluetoothDevice is null");
1001 return CA_STATUS_OK;
1004 CAResult_t CALEServerSendMulticastMessageImpl(JNIEnv *env, const char* data, uint32_t dataLen)
1006 OIC_LOG_V(DEBUG, TAG, "CALEServerSendMulticastMessageImpl, send to, data: %s", data);
1008 if (!g_connectedDeviceList)
1010 OIC_LOG(ERROR, TAG, "g_connectedDeviceList is null");
1011 return CA_STATUS_FAILED;
1014 // 1. get all the device objects from cache
1015 // 2. connect to the gatt client devices
1016 // 3. write a characteristic for response
1017 // 4. notify it to every devices
1021 for (index = 0; index < u_arraylist_length(g_connectedDeviceList); index++)
1023 jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
1026 OIC_LOG(ERROR, TAG, "jarrayObj is null");
1027 return CA_STATUS_FAILED;
1030 g_isSendingMulticastData = JNI_TRUE;
1031 CANativeLEServerConnect(env, jarrayObj);
1036 return CA_STATUS_OK;
1039 void CALEServerCreateCachedDeviceList()
1041 OIC_LOG(DEBUG, TAG, "CALEServerCreateCachedDeviceList");
1043 // create new object array
1044 if (g_connectedDeviceList == NULL)
1046 OIC_LOG(DEBUG, TAG, "Create device list");
1048 g_connectedDeviceList = u_arraylist_create();
1052 jboolean CALEServerIsDeviceInList(JNIEnv *env, const char* remoteAddress)
1054 OIC_LOG(DEBUG, TAG, "CALEServerIsDeviceInList");
1056 if (g_connectedDeviceList == NULL)
1057 OIC_LOG(ERROR, TAG, "list is null");
1059 uint32_t len = u_arraylist_length(g_connectedDeviceList);
1062 for (index = 0; index < u_arraylist_length(g_connectedDeviceList); index++)
1064 jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
1068 OIC_LOG(ERROR, TAG, "jarrayObj is null");
1072 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
1073 if (!jni_setAddress)
1075 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
1079 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress,
1082 if (!strcmp(remoteAddress, setAddress))
1084 OIC_LOG(DEBUG, TAG, "the device is already set");
1093 OIC_LOG(DEBUG, TAG, "no device in list");
1097 void CALEServerAddDeviceToList(JNIEnv *env, jobject device)
1101 OIC_LOG(ERROR, TAG, "device is null");
1105 if (g_connectedDeviceList == NULL)
1107 OIC_LOG(ERROR, TAG, "list is null");
1111 jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
1112 if (!jni_remoteAddress)
1114 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
1118 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
1120 if (CALEServerIsDeviceInList(env, remoteAddress) == JNI_FALSE)
1122 jobject gdevice = (*env)->NewGlobalRef(env, device);
1123 u_arraylist_add(g_connectedDeviceList, gdevice);
1124 OIC_LOG(DEBUG, TAG, "Set Object to Array as Element");
1128 void CALEServerRemoveAllDevices(JNIEnv *env)
1130 OIC_LOG(DEBUG, TAG, "CALEServerRemoveAllDevices");
1132 if (!g_connectedDeviceList)
1134 OIC_LOG(ERROR, TAG, "no deviceList");
1139 for (index = 0; index < u_arraylist_length(g_connectedDeviceList); index++)
1141 jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
1145 (*env)->DeleteGlobalRef(env, jarrayObj);
1149 OICFree(g_connectedDeviceList);
1150 g_connectedDeviceList = NULL;
1154 void CALEServerRemoveDevice(JNIEnv *env, jstring address)
1156 OIC_LOG(DEBUG, TAG, "CALEServerRemoveDevice");
1158 if (!g_connectedDeviceList)
1160 OIC_LOG(ERROR, TAG, "no deviceList");
1165 for (index = 0; index < u_arraylist_length(g_connectedDeviceList); index++)
1167 jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
1171 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
1172 if (!jni_setAddress)
1174 OIC_LOG(ERROR, TAG, "wrong device address");
1177 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress,
1179 const char* remoteAddress = (*env)->GetStringUTFChars(env, address,
1182 if (!strcmp(setAddress, remoteAddress))
1184 OIC_LOG_V(DEBUG, TAG, "device address : %s", remoteAddress);
1185 (*env)->DeleteGlobalRef(env, jarrayObj);
1187 CALEServerReorderinglist(index);
1191 }OIC_LOG(DEBUG, TAG, "no target object");
1195 void CALEServerReorderinglist(uint32_t index)
1197 if (index >= g_connectedDeviceList->length)
1200 if (index < g_connectedDeviceList->length - 1)
1202 memmove(&g_connectedDeviceList->data[index], &g_connectedDeviceList->data[index + 1],
1203 (g_connectedDeviceList->length - index - 1) * sizeof(void *));
1206 g_connectedDeviceList->size--;
1207 g_connectedDeviceList->length--;
1210 JNIEXPORT void JNICALL
1211 Java_com_iotivity_jar_caleinterface_CALeGattServerServiceAddedCallback(JNIEnv *env, jobject obj,
1213 jobject gattService)
1215 OIC_LOG_V(DEBUG, TAG, "CALeInterface - Gatt Service Added Callback(%d)", status);
1218 JNIEXPORT void JNICALL
1219 Java_com_iotivity_jar_caleinterface_CALeGattServerCharacteristicReadRequestCallback(
1220 JNIEnv *env, jobject obj, jobject device, jint requestId, jint offset,
1221 jobject characteristic, jbyteArray data)
1223 OIC_LOG(DEBUG, TAG, "CALeInterface - Gatt Server Characteristic Read Request Callback");
1225 CANativeLEServerSendResponse(env, device, requestId, 0, offset, NULL);
1228 JNIEXPORT void JNICALL
1229 Java_com_iotivity_jar_caleinterface_CALeGattServerCharacteristicWriteRequestCallback(
1230 JNIEnv *env, jobject obj, jobject device, jint requestId, jobject characteristic,
1231 jbyteArray data, jboolean preparedWrite, jboolean responseNeeded, jint offset,
1234 OIC_LOG(DEBUG, TAG, "CALeInterface - Gatt Server Characteristic Write Request Callback");
1236 CANativeLEServerSendResponse(env, device, requestId, 0, offset, value);
1240 OIC_LOG(ERROR, TAG, "Reqeust data is null");
1244 // get Byte Array and covert to char*
1245 jint length = (*env)->GetArrayLength(env, data);
1248 jbyte *jni_byte_requestData = (jbyte *) (*env)->GetByteArrayElements(env, data, &isCopy);
1250 char* requestData = NULL;
1251 requestData = (char*) OICCalloc(1, length + 1);
1252 if (NULL == requestData)
1254 OIC_LOG(ERROR, TAG, "requestData is null");
1258 strncpy(requestData, (char*) jni_byte_requestData, length);
1259 requestData[length] = '\0';
1260 (*env)->ReleaseByteArrayElements(env, data, jni_byte_requestData, JNI_ABORT);
1262 jstring jni_address = CALEGetAddressFromBTDevice(env, device);
1263 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
1264 OIC_LOG_V(DEBUG, TAG, "remote device address : %s", address);
1266 g_packetReceiveCallback(address, requestData);
1269 JNIEXPORT void JNICALL
1270 Java_com_iotivity_jar_caleinterface_CALeGattServerDescriptorReadRequestCallback(JNIEnv *env,
1277 OIC_LOG(DEBUG, TAG, "CALeInterface_CALeGattServerDescriptorReadRequestCallback");
1280 JNIEXPORT void JNICALL
1281 Java_com_iotivity_jar_caleinterface_CALeGattServerDescriptorWriteRequestCallback(
1282 JNIEnv *env, jobject obj, jobject device, jint requestId, jobject descriptor,
1283 jboolean preparedWrite, jboolean responseNeeded, jint offset, jbyteArray value)
1285 OIC_LOG(DEBUG, TAG, "CALeInterface_CALeGattServerDescriptorWriteRequestCallback");
1288 JNIEXPORT void JNICALL
1289 Java_com_iotivity_jar_caleinterface_CALeGattServerExecuteWriteCallback(JNIEnv *env, jobject obj,
1294 OIC_LOG(DEBUG, TAG, "CALeInterface_CALeGattServerExecuteWriteCallback");
1296 CANativeLEServerSendResponse(env, device, requestId, 0, 0, NULL);
1299 JNIEXPORT void JNICALL
1300 Java_com_iotivity_jar_caleinterface_CALeGattServerNotificationSentCallback(JNIEnv *env, jobject obj,
1304 OIC_LOG(DEBUG, TAG, "CALeInterface - Gatt Server Notification Sent Callback");
1307 JNIEXPORT void JNICALL
1308 Java_com_iotivity_jar_caleinterface_CALeAdvertiseStartSuccessCallback(JNIEnv *env, jobject obj,
1309 jobject settingsInEffect)
1311 OIC_LOG(DEBUG, TAG, "CALeInterface - LE Advertise Start Success Callback");
1314 JNIEXPORT void JNICALL
1315 Java_com_iotivity_jar_caleinterface_CALeAdvertiseStartFailureCallback(JNIEnv *env, jobject obj,
1318 OIC_LOG_V(ERROR, TAG, "CALeInterface - LE Advertise Start Failure Callback(%)", errorCode);
1321 JNIEXPORT void JNICALL
1322 Java_com_iotivity_jar_caleinterface_CARegisterLeGattServerCallback(JNIEnv *env, jobject obj,
1325 OIC_LOG(DEBUG, TAG, "CALeInterface - Register Le Gatt Server Callback");
1327 g_bluetoothGattServerCallback = (*env)->NewGlobalRef(env, callback);
1330 JNIEXPORT void JNICALL
1331 Java_com_iotivity_jar_caleinterface_CARegisterBluetoothLeAdvertiseCallback(JNIEnv *env, jobject obj,
1334 OIC_LOG(DEBUG, TAG, "CALeInterface - Register Le Advertise Callback");
1336 g_leAdvertiseCallback = (*env)->NewGlobalRef(env, callback);
1339 JNIEXPORT void JNICALL
1340 Java_com_iotivity_jar_caleinterface_CALeGattServerConnectionStateChangeCallback(JNIEnv *env,
1346 OIC_LOG(DEBUG, TAG, "CALeInterface - Gatt Server ConnectionStateChange Callback");
1348 OIC_LOG_V(DEBUG, TAG, "New connection State: %d", newState);
1352 OIC_LOG(ERROR, TAG, "device is null");
1356 jclass jni_cid_bluetoothProfile = (*env)->FindClass(env, "android/bluetooth/BluetoothProfile");
1358 jfieldID jni_fid_state_connected = (*env)->GetStaticFieldID(env, jni_cid_bluetoothProfile,
1359 "STATE_CONNECTED", "I");
1361 jfieldID jni_fid_state_disconnected = (*env)->GetStaticFieldID(env, jni_cid_bluetoothProfile,
1362 "STATE_DISCONNECTED", "I");
1365 jint jni_int_state_connected = (*env)->GetStaticIntField(env, jni_cid_bluetoothProfile,
1366 jni_fid_state_connected);
1368 // STATE_DISCONNECTED
1369 jint jni_int_state_disconnected = (*env)->GetStaticIntField(env, jni_cid_bluetoothProfile,
1370 jni_fid_state_disconnected);
1372 if (newState == jni_int_state_connected)
1375 OIC_LOG(DEBUG, TAG, "LE CONNECTED");
1377 jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
1378 if (!jni_remoteAddress)
1380 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
1384 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
1386 if (g_connectedDeviceList == NULL)
1388 OIC_LOG(ERROR, TAG, "g_connectedDeviceList is null");
1391 if (CALEServerIsDeviceInList(env, remoteAddress) == JNI_FALSE)
1393 OIC_LOG(DEBUG, TAG, "add connected device to cache");
1394 CALEServerAddDeviceToList(env, device);
1397 else if (newState == jni_int_state_disconnected)
1399 OIC_LOG(DEBUG, TAG, "LE DISCONNECTED");