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 ******************************************************************/
26 #include "calestate.h"
27 #include "caleclient.h"
28 #include "caleserver.h"
29 #include "caleutils.h"
30 #include "caleinterface.h"
31 #include "caadapterutils.h"
33 #include "uarraylist.h"
35 #include "oic_malloc.h"
36 #include "oic_string.h"
37 #include "cathreadpool.h" /* for thread pool */
39 #include "uarraylist.h"
40 #include "org_iotivity_ca_CaLeClientInterface.h"
41 #include "caleclient_utils.h"
42 #include "caleclient.h"
44 JNIEXPORT void JNICALL
45 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env, jobject obj,
48 OIC_LOG(DEBUG, TAG, "CaLeRegisterLeScanCallback");
49 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
50 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
51 VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
53 g_leScanCallback = (*env)->NewGlobalRef(env, callback);
54 CACheckJNIException(env);
57 JNIEXPORT void JNICALL
58 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallbackForV21(JNIEnv *env,
62 OIC_LOG(DEBUG, TAG, "caLeRegisterLeScanCallbackForV21");
63 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
64 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
65 VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
67 g_leScanCallback = (*env)->NewGlobalRef(env, callback);
68 CACheckJNIException(env);
71 JNIEXPORT void JNICALL
72 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, jobject obj,
75 OIC_LOG(DEBUG, TAG, "CaLeRegisterGattCallback");
76 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
77 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
78 VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
80 g_leGattCallback = (*env)->NewGlobalRef(env, callback);
81 CACheckJNIException(env);
84 JNIEXPORT void JNICALL
85 Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
88 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
89 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
90 VERIFY_NON_NULL_VOID(device, TAG, "device is null");
92 CAResult_t res = CALEClientAddScanDeviceToList(env, device);
93 if (CA_STATUS_OK != res)
95 OIC_LOG_V(ERROR, TAG, "CALEClientAddScanDeviceToList has failed : %d", res);
99 JNIEXPORT void JNICALL
100 Java_org_iotivity_ca_CaLeClientInterface_caLeScanFailedCallback(JNIEnv *env, jobject obj,
103 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
104 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
109 OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_ALREADY_STARTED");
114 "BLE scan has failed, error is SCAN_FAILED_APPLICATION_REGISTRATION_FAILED");
118 OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_INTERNAL_ERROR");
122 OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_FEATURE_UNSUPPORTED");
126 OIC_LOG(ERROR, TAG, "BLE scan has failed with unknown error");
132 * Class: org_iotivity_ca_jar_caleinterface
133 * Method: CALeGattConnectionStateChangeCallback
134 * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
136 JNIEXPORT void JNICALL
137 Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(JNIEnv *env,
143 OIC_LOG_V(INFO, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status,
145 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
146 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
147 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
149 jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
151 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
154 OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGattObj has failed");
158 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
161 OIC_LOG(ERROR, TAG, "address is null");
162 CACheckJNIException(env);
165 OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - address [%s]", address);
167 if (state_connected == newstate)
169 OIC_LOG(DEBUG, TAG, "LE is connected");
170 if (GATT_SUCCESS == status)
172 CAResult_t res = CALEUpdateDeviceState(address,
173 CA_LE_CONNECTION_STATE,
176 g_deviceStateListMutex);
177 (*env)->ReleaseStringUTFChars(env, jni_address, address);
178 if (CA_STATUS_OK != res)
180 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
184 res = CALEClientAddGattobjToList(env, gatt);
185 if (CA_STATUS_OK != res)
187 OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
191 res = CALEClientDiscoverServices(env, gatt);
192 if (CA_STATUS_OK != res)
194 OIC_LOG(ERROR, TAG, "CALEClientDiscoverServices has failed");
200 OIC_LOG(INFO, TAG, "unknown status");
201 (*env)->ReleaseStringUTFChars(env, jni_address, address);
204 else // STATE_DISCONNECTED == newstate
206 OIC_LOG(DEBUG, TAG, "LE is disconnected");
208 if (CALEIsValidState(address, CA_LE_SEND_STATE, STATE_SEND_PREPARING,
209 g_deviceStateList, g_deviceStateListMutex))
211 OIC_LOG(INFO, TAG, "current state is STATE_SEND_PREPARING");
212 CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
215 g_deviceStateListMutex);
216 if (CA_STATUS_OK != res)
218 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
222 CAResult_t res = CALEUpdateDeviceState(address,
223 CA_LE_CONNECTION_STATE,
226 g_deviceStateListMutex);
227 if (CA_STATUS_OK != res)
229 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
231 (*env)->ReleaseStringUTFChars(env, jni_address, address);
233 res = CALEClientGattClose(env, gatt);
234 if (CA_STATUS_OK != res)
236 OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
239 if (CALECheckConnectionStateValue(status))
241 // this state is unexpected reason to disconnect
242 // if the reason is suitable, connection logic of the device will be destroyed.
243 OIC_LOG(INFO, TAG, "connection logic destroy");
247 // other reason except for gatt_success is expected to running
248 // background connection in BT platform.
249 OIC_LOG(INFO, TAG, "unknown status or manual disconnected state");
251 CALEClientUpdateSendCnt(env);
257 CALEClientSendFinish(env, gatt);
262 * Class: org_iotivity_ca_jar_caleinterface
263 * Method: CALeGattServicesDiscoveredCallback
264 * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
266 JNIEXPORT void JNICALL
267 Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIEnv *env,
272 OIC_LOG_V(INFO, TAG, "CALeGattServicesDiscoveredCallback - status %d", status);
273 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
274 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
275 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
277 if (GATT_SUCCESS != status) // discovery error
279 CALEClientSendFinish(env, gatt);
283 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
286 CALEClientSendFinish(env, gatt);
290 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
293 CACheckJNIException(env);
294 CALEClientSendFinish(env, gatt);
298 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
301 OIC_LOG(ERROR, TAG, "jni_uuid is null");
305 jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, gatt, jni_uuid);
306 if (!jni_obj_GattCharacteristic)
308 OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
312 CAResult_t res = CALEClientSetCharacteristicNotification(env, gatt,
313 jni_obj_GattCharacteristic);
314 if (CA_STATUS_OK != res)
316 OIC_LOG(ERROR, TAG, "CALEClientSetCharacteristicNotification has failed");
320 res = CALEClientSetUUIDToDescriptor(env, gatt, jni_obj_GattCharacteristic);
321 if (CA_STATUS_OK != res)
323 OIC_LOG_V(INFO, TAG, "Descriptor is not found : %d", res);
325 res = CALESetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_FALSE,
326 g_deviceStateList, g_deviceStateListMutex);
327 if (CA_STATUS_OK != res)
329 OIC_LOG(ERROR, TAG, "CALESetFlagToState has failed");
333 res = CALEUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
334 STATE_SERVICE_CONNECTED,
336 g_deviceStateListMutex);
337 if (CA_STATUS_OK != res)
339 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
343 res = CALEClientRequestMTU(env, gatt, CA_SUPPORTED_BLE_MTU_SIZE);
344 if (CA_STATUS_OK != res)
346 OIC_LOG(ERROR, TAG, "CALEClientRequestMTU has failed");
352 res = CALESetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_TRUE,
353 g_deviceStateList, g_deviceStateListMutex);
354 if (CA_STATUS_OK != res)
356 OIC_LOG(ERROR, TAG, "CALESetFlagToState has failed");
362 // reset interval scan logic
363 CALERestartScanWithInterval(g_scanIntervalTimePrev, 0, BLE_SCAN_ENABLE);
366 OIC_LOG(INFO, TAG, "ServicesDiscovery is successful");
367 (*env)->ReleaseStringUTFChars(env, jni_address, address);
372 OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
373 (*env)->ReleaseStringUTFChars(env, jni_address, address);
374 CALEClientSendFinish(env, gatt);
379 * Class: org_iotivity_ca_jar_caleinterface
380 * Method: CALeGattCharacteristicWritjclasseCallback
381 * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
383 JNIEXPORT void JNICALL
384 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback(
385 JNIEnv *env, jobject obj, jobject gatt, jbyteArray data, jint status)
387 OIC_LOG_V(INFO, TAG, "CALeGattCharacteristicWriteCallback - status : %d", status);
388 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
389 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
390 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
392 // send success & signal
393 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
399 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
402 CACheckJNIException(env);
406 if (GATT_SUCCESS != status) // error case
408 OIC_LOG(ERROR, TAG, "send failure");
411 CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
412 if (CA_STATUS_OK != res)
414 OIC_LOG(ERROR, TAG, "WriteCharacteristic has failed");
415 oc_mutex_lock(g_threadWriteCharacteristicMutex);
416 g_isSignalSetFlag = true;
417 oc_cond_signal(g_threadWriteCharacteristicCond);
418 oc_mutex_unlock(g_threadWriteCharacteristicMutex);
420 CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
423 g_deviceStateListMutex);
424 if (CA_STATUS_OK != res)
426 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
429 if (g_clientErrorCallback)
431 jint length = (*env)->GetArrayLength(env, data);
432 CACheckJNIException(env);
433 g_clientErrorCallback(address, data, length, CA_SEND_FAILED);
434 CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, address, 0, length,
435 false, "writeChar failure");
438 (*env)->ReleaseStringUTFChars(env, jni_address, address);
444 OIC_LOG(DEBUG, TAG, "send success");
445 CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
448 g_deviceStateListMutex);
449 if (CA_STATUS_OK != res)
451 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
454 oc_mutex_lock(g_threadWriteCharacteristicMutex);
455 OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
456 g_isSignalSetFlag = true;
457 oc_cond_signal(g_threadWriteCharacteristicCond);
458 oc_mutex_unlock(g_threadWriteCharacteristicMutex);
460 CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, address, 0,
461 (*env)->GetArrayLength(env, data),
462 true, "writeChar success");
465 (*env)->ReleaseStringUTFChars(env, jni_address, address);
471 CALEClientSendFinish(env, gatt);
476 * Class: org_iotivity_ca_jar_caleinterface
477 * Method: CALeGattCharacteristicChangedCallback
478 * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V
480 JNIEXPORT void JNICALL
481 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback(
482 JNIEnv *env, jobject obj, jobject gatt, jbyteArray data)
484 OIC_LOG(DEBUG, TAG, "CALeGattCharacteristicChangedCallback");
485 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
486 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
487 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
488 VERIFY_NON_NULL_VOID(data, TAG, "data is null");
490 // get Byte Array and convert to uint8_t*
491 jint length = (*env)->GetArrayLength(env, data);
494 jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
495 CACheckJNIException(env);
497 uint8_t* receivedData = OICMalloc(length);
500 OIC_LOG(ERROR, TAG, "receivedData is null");
504 memcpy(receivedData, jni_byte_responseData, length);
505 (*env)->ReleaseByteArrayElements(env, data, jni_byte_responseData, JNI_ABORT);
507 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
510 OIC_LOG(ERROR, TAG, "jni_address is null");
511 OICFree(receivedData);
515 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
518 OIC_LOG(ERROR, TAG, "address is null");
519 CACheckJNIException(env);
520 OICFree(receivedData);
524 OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %p, %d",
525 receivedData, length);
527 uint32_t sentLength = 0;
528 oc_mutex_lock(g_bleServerBDAddressMutex);
529 g_CABLEClientDataReceivedCallback(address, receivedData, length, &sentLength);
530 oc_mutex_unlock(g_bleServerBDAddressMutex);
532 (*env)->ReleaseStringUTFChars(env, jni_address, address);
536 * Class: org_iotivity_ca_jar_caleinterface
537 * Method: CALeGattDescriptorWriteCallback
538 * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
540 JNIEXPORT void JNICALL
541 Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorWriteCallback(JNIEnv *env, jobject obj,
545 OIC_LOG_V(INFO, TAG, "CALeGattDescriptorWriteCallback - status %d", status);
546 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
547 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
548 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
550 if (GATT_SUCCESS != status) // error
555 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
561 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
564 CACheckJNIException(env);
568 CAResult_t res = CALEUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
569 STATE_SERVICE_CONNECTED,
571 g_deviceStateListMutex);
572 (*env)->ReleaseStringUTFChars(env, jni_address, address);
573 if (CA_STATUS_OK != res)
575 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
579 res = CALEClientRequestMTU(env, gatt, CA_SUPPORTED_BLE_MTU_SIZE);
580 if (CA_STATUS_OK != res)
582 OIC_LOG(ERROR, TAG, "CALEClientRequestMTU has failed");
590 CALEClientSendFinish(env, gatt);
594 JNIEXPORT void JNICALL
595 Java_org_iotivity_ca_CaLeClientInterface_caLeGattMtuChangedCallback(JNIEnv *env,
601 OIC_LOG_V(INFO, TAG, "caLeGattMtuChangedCallback - status %d, "
602 "mtu[%d-including Header size 3 byte]", status, mtu);
606 if (0 == status || 133 == status)
610 CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
611 if (CA_STATUS_OK != res)
613 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
618 OIC_LOG(INFO, TAG, "mtu nego is done");
619 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
622 CALEClientSendFinish(env, gatt);
626 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
629 CACheckJNIException(env);
630 (*env)->DeleteLocalRef(env, jni_address);
631 CALEClientSendFinish(env, gatt);
636 CAResult_t res = CALESetMtuSize(address, mtu - CA_BLE_MTU_HEADER_SIZE,
637 g_deviceStateList, g_deviceStateListMutex);
638 if (CA_STATUS_OK != res)
640 OIC_LOG(ERROR, TAG, "CALESetMtuSize has failed");
643 res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
644 STATE_SEND_MTU_NEGO_SUCCESS,
646 g_deviceStateListMutex);
647 if (CA_STATUS_OK != res)
649 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
651 CALEClientUpdateSendCnt(env);
652 (*env)->ReleaseStringUTFChars(env, jni_address, address);
653 (*env)->DeleteLocalRef(env, jni_address);