X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fconnectivity%2Fsrc%2Fbt_le_adapter%2Fandroid%2Fcaleserver.c;h=3cbb821a09f1ef6723b4e63290c1d4e7360c60e5;hb=3c093548382bb2542c87a67e6e5fa32552c29cb3;hp=939ac0bce40e9e9d17b1c2008b7c6391179e0004;hpb=15b36e24c3a6f7a258c097b610809a95f1637dac;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/connectivity/src/bt_le_adapter/android/caleserver.c b/resource/csdk/connectivity/src/bt_le_adapter/android/caleserver.c index 939ac0b..3cbb821 100644 --- a/resource/csdk/connectivity/src/bt_le_adapter/android/caleserver.c +++ b/resource/csdk/connectivity/src/bt_le_adapter/android/caleserver.c @@ -27,34 +27,58 @@ #include "caleutils.h" #include "caleinterface.h" #include "caadapterutils.h" +#include "calestate.h" #include "logger.h" #include "oic_malloc.h" #include "cathreadpool.h" -#include "camutex.h" +#include "octhread.h" #include "uarraylist.h" #include "org_iotivity_ca_CaLeServerInterface.h" -#define TAG PCF("CA_LE_SERVER") +#define TAG PCF("OIC_CA_LE_SERVER") + +#define WAIT_TIME_WRITE_CHARACTERISTIC 10000000 +#define INVALID_STATE -1 static JavaVM *g_jvm = NULL; static jobject g_context = NULL; static jobject g_bluetoothGattServer = NULL; static jobject g_bluetoothGattServerCallback = NULL; static jobject g_leAdvertiseCallback = NULL; +static jobject g_bluetoothManager = NULL; static CAPacketReceiveCallback g_packetReceiveCallback = NULL; static CABLEErrorHandleCallback g_serverErrorCallback; static u_arraylist_t *g_connectedDeviceList = NULL; +static u_arraylist_t *g_deviceStateList = NULL; static bool g_isStartServer = false; static bool g_isInitializedServer = false; +static jbyteArray g_sendBuffer = NULL; +static jobject g_obj_bluetoothDevice = NULL; + static CABLEDataReceivedCallback g_CABLEServerDataReceivedCallback = NULL; -static ca_mutex g_bleReqRespCbMutex = NULL; -static ca_mutex g_bleClientBDAddressMutex = NULL; -static ca_mutex g_connectedDeviceListMutex = NULL; +static oc_mutex g_bleReqRespCbMutex = NULL; +static oc_mutex g_bleClientBDAddressMutex = NULL; +static oc_mutex g_connectedDeviceListMutex = NULL; + +static oc_mutex g_threadSendMutex = NULL; +static oc_mutex g_threadSendNotifyMutex = NULL; +static oc_cond g_threadSendNotifyCond = NULL; +static bool g_isSignalSetFlag = false; + +static oc_mutex g_deviceStateListMutex = NULL; + +static jint g_state_connected = INVALID_STATE; +static jint g_state_disconnected = INVALID_STATE; + +static const char CLASSPATH_BT_ADVERTISE_CB[] = "android/bluetooth/le/AdvertiseCallback"; +static const char CLASSPATH_BT_GATTSERVER[] = "android/bluetooth/BluetoothGattServer"; + +static bool g_setHighQoS = true; void CALEServerJNISetContext() { @@ -85,7 +109,7 @@ CAResult_t CALEServerCreateJniInterfaceObject() } bool isAttached = false; - JNIEnv* env; + JNIEnv* env = NULL; jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { @@ -135,54 +159,72 @@ CAResult_t CALEServerCreateJniInterfaceObject() return CA_STATUS_FAILED; } -jobject CALEServerSetResponseData(JNIEnv *env, jbyteArray responseData) +/** + * get the current connection state of the gatt profile to the remote device. + * @param[in] env JNI interface pointer. + * @param[in] device bluetooth device object + * @return state of the profile connection. + */ +static jint CALEServerGetConnectionState(JNIEnv *env, jobject device) { - OIC_LOG(DEBUG, TAG, "IN - CALEServerSetResponseData"); - VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL); - VERIFY_NON_NULL_RET(responseData, TAG, "responseData is null", NULL); + OIC_LOG(DEBUG, TAG, "CALEServerGetConnectionState"); - if (!g_bluetoothGattServer) + VERIFY_NON_NULL_RET(env, TAG, "env", -1); + VERIFY_NON_NULL_RET(device, TAG, "device", -1); + + jmethodID jni_mid_getConnectionState = CAGetJNIMethodID(env, "android/bluetooth" + "/BluetoothManager", + "getConnectionState", + "(Landroid/bluetooth/BluetoothDevice" + ";I)I"); + if (!jni_mid_getConnectionState) { - OIC_LOG(ERROR, TAG, "Check BluetoothGattServer status"); - return NULL; + OIC_LOG(ERROR, TAG, "jni_mid_getConnectionState is null"); + return -1; } - if (!CALEIsEnableBTAdapter(env)) + if (!g_bluetoothManager) { - OIC_LOG(ERROR, TAG, "BT adapter is not enabled"); - return NULL; + OIC_LOG(ERROR, TAG, "g_bluetoothManager is null"); + return -1; } - OIC_LOG(DEBUG, TAG, "CALEServerSetResponseData"); - - jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env, - "android/bluetooth/BluetoothGattServer"); - if (!jni_cid_bluetoothGattServer) + jint jni_state = (jint)(*env)->CallIntMethod(env, g_bluetoothManager, + jni_mid_getConnectionState, + device, GATT_PROFILE); + if (CACheckJNIException(env)) { - OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null"); - return NULL; + OIC_LOG(ERROR, TAG, "getConnectionState has failed"); + return -1; } - jclass jni_cid_bluetoothGattService = (*env)->FindClass(env, "android/bluetooth/" - "BluetoothGattService"); - if (!jni_cid_bluetoothGattService) + OIC_LOG_V(INFO, TAG, "connection state is %d", jni_state); + return jni_state; +} + +jobject CALEServerSetResponseData(JNIEnv *env, jbyteArray responseData) +{ + OIC_LOG(DEBUG, TAG, "IN - CALEServerSetResponseData"); + VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL); + VERIFY_NON_NULL_RET(responseData, TAG, "responseData is null", NULL); + + if (!g_bluetoothGattServer) { - OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattService is null"); + OIC_LOG(ERROR, TAG, "Check BluetoothGattServer status"); return NULL; } - jclass jni_cid_bluetoothGattCharacteristic = (*env)->FindClass(env, "android/bluetooth/" - "BluetoothGattCharacteristic"); - if (!jni_cid_bluetoothGattCharacteristic) + if (!CALEIsEnableBTAdapter(env)) { - OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattCharacteristic is null"); + OIC_LOG(ERROR, TAG, "BT adapter is not enabled"); return NULL; } - jmethodID jni_mid_getService = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer, - "getService", - "(Ljava/util/UUID;)Landroid/bluetooth/" - "BluetoothGattService;"); + OIC_LOG(DEBUG, TAG, "CALEServerSetResponseData"); + jmethodID jni_mid_getService = CAGetJNIMethodID(env, CLASSPATH_BT_GATTSERVER, + "getService", + "(Ljava/util/UUID;)Landroid/bluetooth/" + "BluetoothGattService;"); if (!jni_mid_getService) { OIC_LOG(ERROR, TAG, "jni_mid_getService is null"); @@ -202,14 +244,16 @@ jobject CALEServerSetResponseData(JNIEnv *env, jbyteArray responseData) if (!jni_obj_bluetoothGattService) { OIC_LOG(ERROR, TAG, "jni_obj_bluetoothGattService is null"); + CACheckJNIException(env); return NULL; } - jmethodID jni_mid_getCharacteristic = (*env)->GetMethodID(env, jni_cid_bluetoothGattService, - "getCharacteristic", - "(Ljava/util/UUID;)" - "Landroid/bluetooth/" - "BluetoothGattCharacteristic;"); + jmethodID jni_mid_getCharacteristic = CAGetJNIMethodID(env, "android/bluetooth/" + "BluetoothGattService", + "getCharacteristic", + "(Ljava/util/UUID;)" + "Landroid/bluetooth/" + "BluetoothGattCharacteristic;"); if (!jni_mid_getCharacteristic) { OIC_LOG(ERROR, TAG, "jni_mid_getCharacteristic is null"); @@ -229,11 +273,13 @@ jobject CALEServerSetResponseData(JNIEnv *env, jbyteArray responseData) if (!jni_obj_bluetoothGattCharacteristic) { OIC_LOG(ERROR, TAG, "jni_obj_bluetoothGattCharacteristic is null"); + CACheckJNIException(env); return NULL; } - jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_bluetoothGattCharacteristic, - "setValue", "([B)Z"); + jmethodID jni_mid_setValue = CAGetJNIMethodID(env, "android/bluetooth/" + "BluetoothGattCharacteristic", + "setValue", "([B)Z"); if (!jni_mid_setValue) { OIC_LOG(ERROR, TAG, "jni_mid_setValue is null"); @@ -246,6 +292,7 @@ jobject CALEServerSetResponseData(JNIEnv *env, jbyteArray responseData) if (JNI_FALSE == jni_boolean_setValue) { OIC_LOG(ERROR, TAG, "Fail to set response data"); + CACheckJNIException(env); } OIC_LOG(DEBUG, TAG, "OUT - CALEServerSetResponseData"); @@ -254,7 +301,7 @@ jobject CALEServerSetResponseData(JNIEnv *env, jbyteArray responseData) CAResult_t CALEServerSendResponseData(JNIEnv *env, jobject device, jobject responseData) { - OIC_LOG(DEBUG, TAG, "IN - CALEServerSendResponseData"); + OIC_LOG(DEBUG, TAG, "CALEServerSendResponseData"); VERIFY_NON_NULL(responseData, TAG, "responseData is null"); VERIFY_NON_NULL(device, TAG, "device is null"); VERIFY_NON_NULL(env, TAG, "env is null"); @@ -265,34 +312,59 @@ CAResult_t CALEServerSendResponseData(JNIEnv *env, jobject device, jobject respo return CA_ADAPTER_NOT_ENABLED; } - jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env, - "android/bluetooth/BluetoothGattServer"); - if (!jni_cid_bluetoothGattServer) + if (!g_bluetoothGattServer) { - OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null"); + OIC_LOG(ERROR, TAG, "g_bluetoothGattServer is not available"); return CA_STATUS_FAILED; } - jmethodID jni_mid_notifyCharacteristicChanged = (*env)->GetMethodID( - env, jni_cid_bluetoothGattServer, "notifyCharacteristicChanged", - "(Landroid/bluetooth/BluetoothDevice;" - "Landroid/bluetooth/BluetoothGattCharacteristic;Z)Z"); + if (g_state_connected != CALEServerGetConnectionState(env, device)) + { + OIC_LOG(ERROR, TAG, "it is not connected state"); + return CA_STATUS_FAILED; + } + + jmethodID jni_mid_notifyCharacteristicChanged = CAGetJNIMethodID(env, + CLASSPATH_BT_GATTSERVER, + "notifyCharacteristicChanged", + "(Landroid/bluetooth/BluetoothDevice;" + "Landroid/bluetooth/" + "BluetoothGattCharacteristic;Z)Z"); if (!jni_mid_notifyCharacteristicChanged) { OIC_LOG(ERROR, TAG, "jni_mid_notifyCharacteristicChanged is null"); return CA_STATUS_FAILED; } + OIC_LOG(DEBUG, TAG, "CALL API - notifyCharacteristicChanged"); + jboolean jni_boolean_notifyCharacteristicChanged = (*env)->CallBooleanMethod( env, g_bluetoothGattServer, jni_mid_notifyCharacteristicChanged, device, responseData, JNI_FALSE); if (JNI_FALSE == jni_boolean_notifyCharacteristicChanged) { OIC_LOG(ERROR, TAG, "Fail to notify characteristic"); + CACheckJNIException(env); return CA_SEND_FAILED; } - OIC_LOG(DEBUG, TAG, "OUT - CALEServerSendResponseData"); + OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag); + oc_mutex_lock(g_threadSendNotifyMutex); + if (!g_isSignalSetFlag) + { + OIC_LOG(DEBUG, TAG, "wait for callback to notify notifyCharacteristic is success"); + if (0 != oc_cond_wait_for(g_threadSendNotifyCond, g_threadSendNotifyMutex, + WAIT_TIME_WRITE_CHARACTERISTIC)) + { + OIC_LOG(ERROR, TAG, "there is no response. notifyCharacteristic has failed"); + oc_mutex_unlock(g_threadSendNotifyMutex); + return CA_STATUS_FAILED; + } + } + // reset flag set by writeCharacteristic Callback + g_isSignalSetFlag = false; + oc_mutex_unlock(g_threadSendNotifyMutex); + OIC_LOG(INFO, TAG, "notifyCharacteristic success"); return CA_STATUS_OK; } @@ -312,18 +384,16 @@ CAResult_t CALEServerSendResponse(JNIEnv *env, jobject device, jint requestId, j return CA_ADAPTER_NOT_ENABLED; } - jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env, - "android/bluetooth/BluetoothGattServer"); - if (!jni_cid_bluetoothGattServer) + if (!g_bluetoothGattServer) { - OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null"); + OIC_LOG(ERROR, TAG, "g_bluetoothGattServer is not available"); return CA_STATUS_FAILED; } - jmethodID jni_mid_sendResponse = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer, - "sendResponse", - "(Landroid/bluetooth/BluetoothDevice;" - "III[B)Z"); + jmethodID jni_mid_sendResponse = CAGetJNIMethodID(env, CLASSPATH_BT_GATTSERVER, + "sendResponse", + "(Landroid/bluetooth/BluetoothDevice;" + "III[B)Z"); if (!jni_mid_sendResponse) { OIC_LOG(ERROR, TAG, "jni_mid_sendResponse is null"); @@ -337,6 +407,7 @@ CAResult_t CALEServerSendResponse(JNIEnv *env, jobject device, jint requestId, j if (JNI_FALSE == jni_boolean_sendResponse) { OIC_LOG(ERROR, TAG, "Fail to send response for gatt characteristic write request"); + CACheckJNIException(env); return CA_SEND_FAILED; } @@ -344,8 +415,15 @@ CAResult_t CALEServerSendResponse(JNIEnv *env, jobject device, jint requestId, j return CA_STATUS_OK; } -CAResult_t CALEStartAdvertise() +CAResult_t CALEServerStartAdvertise() { + if ((caglobals.bleFlags & CA_LE_ADV_DISABLE) || CA_DEFAULT_BT_FLAGS == caglobals.bleFlags) + { + OIC_LOG_V(INFO, TAG, "the advertisement of the bleFlags is disable[%d]", + caglobals.bleFlags); + return CA_STATUS_OK; + } + if (!g_jvm) { OIC_LOG(ERROR, TAG, "g_jvm is null"); @@ -353,7 +431,7 @@ CAResult_t CALEStartAdvertise() } bool isAttached = false; - JNIEnv* env; + JNIEnv* env = NULL; jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { @@ -369,10 +447,10 @@ CAResult_t CALEStartAdvertise() } // start advertise - CAResult_t ret = CALEServerStartAdvertise(env, g_leAdvertiseCallback); + CAResult_t ret = CALEServerStartAdvertiseImpl(env, g_leAdvertiseCallback); if (CA_STATUS_OK != ret) { - OIC_LOG(ERROR, TAG, "CALEServerStartAdvertise has failed"); + OIC_LOG(ERROR, TAG, "CALEServerStartAdvertiseImpl has failed"); } if (isAttached) @@ -382,9 +460,9 @@ CAResult_t CALEStartAdvertise() return ret; } -CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) +CAResult_t CALEServerStartAdvertiseImpl(JNIEnv *env, jobject advertiseCallback) { - OIC_LOG(DEBUG, TAG, "IN - CALEServerStartAdvertise"); + OIC_LOG(DEBUG, TAG, "IN - CALEServerStartAdvertiseImpl"); VERIFY_NON_NULL(env, TAG, "env is null"); VERIFY_NON_NULL(advertiseCallback, TAG, "advertiseCallback is null"); @@ -400,7 +478,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_cid_AdvertiseSettings) { OIC_LOG(ERROR, TAG, "jni_cid_AdvertiseSettings is null"); - return CA_STATUS_FAILED; + goto error_exit; } jmethodID jni_mid_AdvertiseSettings = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings, @@ -408,7 +486,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_mid_AdvertiseSettings) { OIC_LOG(ERROR, TAG, "jni_mid_AdvertiseSettings is null"); - return CA_STATUS_FAILED; + goto error_exit; } jobject jni_AdvertiseSettings = (*env)->NewObject(env, jni_cid_AdvertiseSettings, @@ -416,7 +494,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_AdvertiseSettings) { OIC_LOG(ERROR, TAG, "jni_AdvertiseSettings is null"); - return CA_STATUS_FAILED; + goto error_exit; } jmethodID jni_mid_setAdvertiseMode = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings, @@ -426,7 +504,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_mid_setAdvertiseMode) { OIC_LOG(ERROR, TAG, "jni_mid_setAdvertiseMode is null"); - return CA_STATUS_FAILED; + goto error_exit; } // 0: Low power, 1: Balanced @@ -435,7 +513,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_obj_setAdvertiseMode) { OIC_LOG(ERROR, TAG, "jni_obj_setAdvertiseMode is null"); - return CA_STATUS_FAILED; + goto error_exit; } jmethodID jni_mid_setConnectable = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings, @@ -445,7 +523,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_mid_setConnectable) { OIC_LOG(ERROR, TAG, "jni_mid_setConnectable is null"); - return CA_STATUS_FAILED; + goto error_exit; } jobject jni_obj_setConnectable = (*env)->CallObjectMethod(env, jni_AdvertiseSettings, @@ -453,7 +531,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_obj_setConnectable) { OIC_LOG(ERROR, TAG, "jni_obj_setConnectable is null"); - return CA_STATUS_FAILED; + goto error_exit; } jmethodID jni_mid_setTimeout = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings, "setTimeout", @@ -462,7 +540,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_mid_setTimeout) { OIC_LOG(ERROR, TAG, "jni_mid_setTimeout is null"); - return CA_STATUS_FAILED; + goto error_exit; } //A value of 0 will disable the time limit @@ -471,7 +549,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_obj_setTimeout) { OIC_LOG(ERROR, TAG, "jni_obj_setTimeout is null"); - return CA_STATUS_FAILED; + goto error_exit; } jclass jni_cid_AdvertiseDataBuilder = (*env)->FindClass(env, @@ -480,7 +558,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_cid_AdvertiseDataBuilder) { OIC_LOG(ERROR, TAG, "jni_cid_AdvertiseDataBuilder is null"); - return CA_STATUS_FAILED; + goto error_exit; } jmethodID jni_mid_AdvertiseDataBuilder = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder, @@ -488,7 +566,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_mid_AdvertiseDataBuilder) { OIC_LOG(ERROR, TAG, "jni_mid_AdvertiseDataBuilder is null"); - return CA_STATUS_FAILED; + goto error_exit; } jobject jni_AdvertiseDataBuilder = (*env)->NewObject(env, jni_cid_AdvertiseDataBuilder, @@ -496,7 +574,16 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_AdvertiseDataBuilder) { OIC_LOG(ERROR, TAG, "jni_AdvertiseDataBuilder is null"); - return CA_STATUS_FAILED; + goto error_exit; + } + + jobject jni_AdvertiseDataBuilderForScanRsp = (*env)->NewObject(env, + jni_cid_AdvertiseDataBuilder, + jni_mid_AdvertiseDataBuilder); + if (!jni_AdvertiseDataBuilderForScanRsp) + { + OIC_LOG(ERROR, TAG, "jni_AdvertiseDataBuilderForScanRsp is null"); + goto error_exit; } jobject jni_obj_serviceUUID = CALEGetUuidFromString(env, OIC_GATT_SERVICE_UUID); @@ -520,7 +607,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_mid_addServiceUuid) { OIC_LOG(ERROR, TAG, "jni_mid_addServiceUuid is null"); - return CA_STATUS_FAILED; + goto error_exit; } jobject jni_obj_addServiceUuid = (*env)->CallObjectMethod(env, jni_AdvertiseDataBuilder, @@ -529,7 +616,30 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_obj_addServiceUuid) { OIC_LOG(ERROR, TAG, "jni_obj_addServiceUuid is null"); - return CA_STATUS_FAILED; + goto error_exit; + } + + // Device name has to be included in advertise packet after Android API 23 + OIC_LOG(DEBUG, TAG, "device name will be added into advertise packet"); + jmethodID jni_mid_setIncludeDeviceName = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder, + "setIncludeDeviceName", + "(Z)Landroid/" + "bluetooth/le/" + "AdvertiseData$Builder;"); + if (!jni_mid_setIncludeDeviceName) + { + OIC_LOG(ERROR, TAG, "jni_mid_setIncludeDeviceName is null"); + goto error_exit; + } + + jobject jni_obj_setIncludeDeviceName = (*env)->CallObjectMethod(env, + jni_AdvertiseDataBuilderForScanRsp, + jni_mid_setIncludeDeviceName, + JNI_TRUE); + if (!jni_obj_setIncludeDeviceName) + { + OIC_LOG(ERROR, TAG, "jni_obj_setIncludeDeviceName is null"); + goto error_exit; } jclass jni_cid_BTAdapter = (*env)->FindClass(env, "android/bluetooth/BluetoothAdapter"); @@ -546,7 +656,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_mid_getDefaultAdapter) { OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null"); - return CA_STATUS_FAILED; + goto error_exit; } jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter, @@ -554,7 +664,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_obj_BTAdapter) { OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null"); - return CA_STATUS_FAILED; + goto error_exit; } jmethodID jni_mid_getBluetoothLeAdvertiser = (*env)->GetMethodID(env, jni_cid_BTAdapter, @@ -564,7 +674,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_mid_getBluetoothLeAdvertiser) { OIC_LOG(ERROR, TAG, "jni_mid_getBluetoothLeAdvertiser is null"); - return CA_STATUS_FAILED; + goto error_exit; } jobject jni_obj_getBluetoothLeAdvertiser = (*env)->CallObjectMethod( @@ -572,7 +682,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_obj_getBluetoothLeAdvertiser) { OIC_LOG(ERROR, TAG, "jni_obj_getBluetoothLeAdvertiser is null"); - return CA_STATUS_FAILED; + goto error_exit; } jmethodID jni_mid_build_LeAdvertiseSettings = (*env)->GetMethodID(env, @@ -583,7 +693,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_mid_build_LeAdvertiseSettings) { OIC_LOG(ERROR, TAG, "jni_mid_build_LeAdvertiseSettings is null"); - return CA_STATUS_FAILED; + goto error_exit; } jobject jni_obj_build_LeAdvertiseSettings = (*env)->CallObjectMethod( @@ -591,7 +701,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_obj_build_LeAdvertiseSettings) { OIC_LOG(ERROR, TAG, "jni_obj_build_LeAdvertiseSettings is null"); - return CA_STATUS_FAILED; + goto error_exit; } jmethodID jni_mid_build_LeAdvertiseData = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder, @@ -601,7 +711,7 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_mid_build_LeAdvertiseData) { OIC_LOG(ERROR, TAG, "jni_mid_build_LeAdvertiseData is null"); - return CA_STATUS_FAILED; + goto error_exit; } jobject jni_obj_build_LeAdvertiseData = (*env)->CallObjectMethod(env, jni_AdvertiseDataBuilder, @@ -609,50 +719,91 @@ CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_obj_build_LeAdvertiseData) { OIC_LOG(ERROR, TAG, "jni_obj_build_LeAdvertiseData is null"); - return CA_STATUS_FAILED; + goto error_exit; } - jclass jni_cid_leAdvertiser = (*env)->FindClass(env, - "android/bluetooth/le/BluetoothLeAdvertiser"); - if (!jni_cid_leAdvertiser) + jobject jni_obj_build_LeAdvertiseDataForScanRsp = (*env)->CallObjectMethod(env, + jni_AdvertiseDataBuilderForScanRsp, + jni_mid_build_LeAdvertiseData); + if (!jni_obj_build_LeAdvertiseDataForScanRsp) { - OIC_LOG(ERROR, TAG, "jni_cid_leAdvertiser is null"); - return CA_STATUS_FAILED; + OIC_LOG(ERROR, TAG, "jni_obj_build_LeAdvertiseDataForScanRsp is null"); + goto error_exit; } - jmethodID jni_mid_startAdvertising = (*env)->GetMethodID(env, jni_cid_leAdvertiser, - "startAdvertising", - "(Landroid/bluetooth/le/" - "AdvertiseSettings;Landroid/bluetooth/" - "le/AdvertiseData;Landroid/bluetooth/" - "le/AdvertiseCallback;)V"); + jmethodID jni_mid_startAdvertising = CAGetJNIMethodID(env, "android/bluetooth/le/" + "BluetoothLeAdvertiser", + "startAdvertising", + "(Landroid/bluetooth/le/" + "AdvertiseSettings;Landroid/bluetooth/" + "le/AdvertiseData;Landroid/bluetooth/" + "le/AdvertiseData;Landroid/bluetooth/" + "le/AdvertiseCallback;)V"); if (!jni_mid_startAdvertising) { - OIC_LOG(ERROR, TAG, "jni_mid_startAdvertising is null"); - return CA_STATUS_FAILED; + OIC_LOG(ERROR, TAG, "jni_mid_startAdvertising is null"); + return CA_STATUS_FAILED; } (*env)->CallVoidMethod(env, jni_obj_getBluetoothLeAdvertiser, jni_mid_startAdvertising, jni_obj_build_LeAdvertiseSettings, jni_obj_build_LeAdvertiseData, - advertiseCallback); - - if ((*env)->ExceptionCheck(env)) + jni_obj_build_LeAdvertiseDataForScanRsp, advertiseCallback); + if (CACheckJNIException(env)) { OIC_LOG(ERROR, TAG, "StartAdvertising has failed"); - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); return CA_STATUS_FAILED; } OIC_LOG(DEBUG, TAG, "Advertising started!!"); - OIC_LOG(DEBUG, TAG, "OUT - CALEServerStartAdvertise"); return CA_STATUS_OK; + +error_exit: + CACheckJNIException(env); + return CA_STATUS_FAILED; } -CAResult_t CALEServerStopAdvertise(JNIEnv *env, jobject advertiseCallback) +CAResult_t CALEServerStopAdvertise() { - OIC_LOG(DEBUG, TAG, "LEServerStopAdvertise"); + if (!g_jvm) + { + OIC_LOG(ERROR, TAG, "g_jvm is null"); + return CA_STATUS_FAILED; + } + + bool isAttached = false; + JNIEnv* env = NULL; + jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); + if (JNI_OK != res) + { + OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer"); + res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); + + if (JNI_OK != res) + { + OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed"); + return CA_STATUS_FAILED; + } + isAttached = true; + } + + CAResult_t ret = CALEServerStopAdvertiseImpl(env, g_leAdvertiseCallback); + if (CA_STATUS_OK != ret) + { + OIC_LOG(ERROR, TAG, "CALEServerStopAdvertise has failed"); + } + + if (isAttached) + { + (*g_jvm)->DetachCurrentThread(g_jvm); + } + + return ret; +} + +CAResult_t CALEServerStopAdvertiseImpl(JNIEnv *env, jobject advertiseCallback) +{ + OIC_LOG(DEBUG, TAG, "CALEServerStopAdvertiseImpl"); VERIFY_NON_NULL(env, TAG, "env is null"); VERIFY_NON_NULL(advertiseCallback, TAG, "advertiseCallback is null"); @@ -666,15 +817,7 @@ CAResult_t CALEServerStopAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_cid_BTAdapter) { OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null"); - return CA_STATUS_FAILED; - } - - jclass jni_cid_leAdvertiser = (*env)->FindClass(env, - "android/bluetooth/le/BluetoothLeAdvertiser"); - if (!jni_cid_leAdvertiser) - { - OIC_LOG(ERROR, TAG, "jni_cid_leAdvertiser is null"); - return CA_STATUS_FAILED; + goto error_exit; } jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter, @@ -684,7 +827,7 @@ CAResult_t CALEServerStopAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_mid_getDefaultAdapter) { OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null"); - return CA_STATUS_FAILED; + goto error_exit; } jmethodID jni_mid_getBTLeAdvertiser = (*env)->GetMethodID(env, jni_cid_BTAdapter, @@ -694,17 +837,18 @@ CAResult_t CALEServerStopAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_mid_getBTLeAdvertiser) { OIC_LOG(ERROR, TAG, "jni_mid_getBTLeAdvertiser is null"); - return CA_STATUS_FAILED; + goto error_exit; } - jmethodID jni_mid_stopAdvertising = (*env)->GetMethodID(env, jni_cid_leAdvertiser, - "stopAdvertising", - "(Landroid/bluetooth/le/" - "AdvertiseCallback;)V"); + jmethodID jni_mid_stopAdvertising = CAGetJNIMethodID(env, "android/bluetooth/le/" + "BluetoothLeAdvertiser", + "stopAdvertising", + "(Landroid/bluetooth/le/" + "AdvertiseCallback;)V"); if (!jni_mid_stopAdvertising) { OIC_LOG(ERROR, TAG, "jni_mid_stopAdvertising is null"); - return CA_STATUS_FAILED; + goto error_exit; } jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter, @@ -712,7 +856,7 @@ CAResult_t CALEServerStopAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_obj_BTAdapter) { OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null"); - return CA_STATUS_FAILED; + goto error_exit; } jobject jni_obj_getBluetoothLeAdvertiser = (*env)->CallObjectMethod(env, jni_obj_BTAdapter, @@ -720,21 +864,23 @@ CAResult_t CALEServerStopAdvertise(JNIEnv *env, jobject advertiseCallback) if (!jni_obj_getBluetoothLeAdvertiser) { OIC_LOG(ERROR, TAG, "jni_obj_getBluetoothLeAdvertiser is null"); - return CA_STATUS_FAILED; + goto error_exit; } (*env)->CallVoidMethod(env, jni_obj_getBluetoothLeAdvertiser, jni_mid_stopAdvertising, advertiseCallback); - if ((*env)->ExceptionCheck(env)) + if (CACheckJNIException(env)) { OIC_LOG(ERROR, TAG, "getBluetoothLeAdvertiser has failed"); - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); return CA_STATUS_FAILED; } OIC_LOG(DEBUG, TAG, "Advertising stopped!!"); return CA_STATUS_OK; + +error_exit: + CACheckJNIException(env); + return CA_STATUS_FAILED; } CAResult_t CALEServerStartGattServer(JNIEnv *env, jobject gattServerCallback) @@ -797,21 +943,14 @@ jobject CALEServerOpenGattServer(JNIEnv *env) if (!CALEIsEnableBTAdapter(env)) { OIC_LOG(ERROR, TAG, "BT adapter is not enabled"); - return NULL; + goto error_exit; } jclass jni_cid_context = (*env)->FindClass(env, "android/content/Context"); if (!jni_cid_context) { OIC_LOG(ERROR, TAG, "jni_cid_context is null"); - return NULL; - } - - jclass jni_cid_bluetoothManager = (*env)->FindClass(env, "android/bluetooth/BluetoothManager"); - if (!jni_cid_bluetoothManager) - { - OIC_LOG(ERROR, TAG, "jni_cid_bluetoothManager is null"); - return NULL; + goto error_exit; } jfieldID jni_fid_bluetoothService = (*env)->GetStaticFieldID(env, jni_cid_context, @@ -820,7 +959,7 @@ jobject CALEServerOpenGattServer(JNIEnv *env) if (!jni_fid_bluetoothService) { OIC_LOG(ERROR, TAG, "jni_fid_bluetoothService is null"); - return NULL; + goto error_exit; } jmethodID jni_mid_getSystemService = (*env)->GetMethodID(env, jni_cid_context, @@ -830,16 +969,17 @@ jobject CALEServerOpenGattServer(JNIEnv *env) if (!jni_mid_getSystemService) { OIC_LOG(ERROR, TAG, "jni_mid_getSystemService is null"); - return NULL; + goto error_exit; } - jmethodID jni_mid_openGattServer = (*env)->GetMethodID(env, jni_cid_bluetoothManager, - "openGattServer", - "(Landroid/content/Context;" - "Landroid/bluetooth/" - "BluetoothGattServerCallback;)" - "Landroid/bluetooth/" - "BluetoothGattServer;"); + jmethodID jni_mid_openGattServer = CAGetJNIMethodID(env, "android/bluetooth/" + "BluetoothManager", + "openGattServer", + "(Landroid/content/Context;" + "Landroid/bluetooth/" + "BluetoothGattServerCallback;)" + "Landroid/bluetooth/" + "BluetoothGattServer;"); if (!jni_mid_openGattServer) { OIC_LOG(ERROR, TAG, "jni_mid_openGattServer is null"); @@ -851,7 +991,7 @@ jobject CALEServerOpenGattServer(JNIEnv *env) if (!jni_obj_bluetoothService) { OIC_LOG(ERROR, TAG, "jni_obj_bluetoothService is null"); - return NULL; + goto error_exit; } jobject jni_obj_bluetoothManager = (*env)->CallObjectMethod(env, g_context, @@ -860,8 +1000,14 @@ jobject CALEServerOpenGattServer(JNIEnv *env) if (!jni_obj_bluetoothManager) { OIC_LOG(ERROR, TAG, "jni_obj_bluetoothManager is null"); - return NULL; + goto error_exit; + } + + if (g_bluetoothManager) + { + (*env)->DeleteGlobalRef(env, g_bluetoothManager); } + g_bluetoothManager = (*env)->NewGlobalRef(env, jni_obj_bluetoothManager); jobject jni_obj_bluetoothGattServer = (*env)->CallObjectMethod(env, jni_obj_bluetoothManager, jni_mid_openGattServer, @@ -870,11 +1016,15 @@ jobject CALEServerOpenGattServer(JNIEnv *env) if (!jni_obj_bluetoothGattServer) { OIC_LOG(ERROR, TAG, "jni_obj_bluetoothGattServer is null"); - return NULL; + goto error_exit; } OIC_LOG(DEBUG, TAG, "OUT - CALEServerOpenGattServer"); return jni_obj_bluetoothGattServer; + +error_exit: + CACheckJNIException(env); + return NULL; } jobject CALEServerCreateGattService(JNIEnv *env) @@ -893,7 +1043,7 @@ jobject CALEServerCreateGattService(JNIEnv *env) if (!jni_cid_bluetoothGattService) { OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattService is null"); - return NULL; + goto error_exit; } jclass jni_cid_bluetoothGattCharacteristic = (*env)->FindClass(env, "android/bluetooth/" @@ -901,7 +1051,7 @@ jobject CALEServerCreateGattService(JNIEnv *env) if (!jni_cid_bluetoothGattCharacteristic) { OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattCharacteristic is null"); - return NULL; + goto error_exit; } jfieldID jni_fid_serviceType = (*env)->GetStaticFieldID(env, jni_cid_bluetoothGattService, @@ -909,25 +1059,50 @@ jobject CALEServerCreateGattService(JNIEnv *env) if (!jni_fid_serviceType) { OIC_LOG(ERROR, TAG, "jni_fid_serviceType is null"); - return NULL; + goto error_exit; } - jfieldID jni_fid_readProperties = (*env)->GetStaticFieldID(env, - jni_cid_bluetoothGattCharacteristic, - "PROPERTY_NOTIFY", "I"); - if (!jni_fid_readProperties) + jfieldID jni_fid_readProperties = NULL; + jfieldID jni_fid_writeProperties = NULL; + if (g_setHighQoS) { - OIC_LOG(ERROR, TAG, "jni_fid_readProperties is null"); - return NULL; - } + jni_fid_readProperties = (*env)->GetStaticFieldID(env, + jni_cid_bluetoothGattCharacteristic, + "PROPERTY_INDICATE", "I"); + if (!jni_fid_readProperties) + { + OIC_LOG(ERROR, TAG, "jni_fid_readProperties is null"); + goto error_exit; + } - jfieldID jni_fid_writeProperties = (*env)->GetStaticFieldID(env, - jni_cid_bluetoothGattCharacteristic, - "PROPERTY_WRITE_NO_RESPONSE", "I"); - if (!jni_fid_writeProperties) + jni_fid_writeProperties = (*env)->GetStaticFieldID(env, + jni_cid_bluetoothGattCharacteristic, + "PROPERTY_WRITE", "I"); + if (!jni_fid_writeProperties) + { + OIC_LOG(ERROR, TAG, "jni_fid_writeProperties is null"); + goto error_exit; + } + } + else { - OIC_LOG(ERROR, TAG, "jni_fid_writeProperties is null"); - return NULL; + jni_fid_readProperties = (*env)->GetStaticFieldID(env, + jni_cid_bluetoothGattCharacteristic, + "PROPERTY_NOTIFY", "I"); + if (!jni_fid_readProperties) + { + OIC_LOG(ERROR, TAG, "jni_fid_readProperties is null"); + goto error_exit; + } + + jni_fid_writeProperties = (*env)->GetStaticFieldID(env, + jni_cid_bluetoothGattCharacteristic, + "PROPERTY_WRITE_NO_RESPONSE", "I"); + if (!jni_fid_writeProperties) + { + OIC_LOG(ERROR, TAG, "jni_fid_writeProperties is null"); + goto error_exit; + } } jfieldID jni_fid_readPermissions = (*env)->GetStaticFieldID(env, @@ -936,7 +1111,7 @@ jobject CALEServerCreateGattService(JNIEnv *env) if (!jni_fid_readPermissions) { OIC_LOG(ERROR, TAG, "jni_fid_readPermissions is null"); - return NULL; + goto error_exit; } jfieldID jni_fid_writePermissions = (*env)->GetStaticFieldID( @@ -944,7 +1119,7 @@ jobject CALEServerCreateGattService(JNIEnv *env) if (!jni_fid_writePermissions) { OIC_LOG(ERROR, TAG, "jni_fid_writePermissions is null"); - return NULL; + goto error_exit; } jmethodID jni_mid_bluetoothGattService = (*env)->GetMethodID(env, jni_cid_bluetoothGattService, @@ -952,7 +1127,7 @@ jobject CALEServerCreateGattService(JNIEnv *env) if (!jni_mid_bluetoothGattService) { OIC_LOG(ERROR, TAG, "jni_mid_bluetoothGattService is null"); - return NULL; + goto error_exit; } jmethodID jni_mid_addCharacteristic = (*env)->GetMethodID(env, jni_cid_bluetoothGattService, @@ -962,7 +1137,7 @@ jobject CALEServerCreateGattService(JNIEnv *env) if (!jni_mid_addCharacteristic) { OIC_LOG(ERROR, TAG, "jni_mid_addCharacteristic is null"); - return NULL; + goto error_exit; } jmethodID jni_mid_bluetoothGattCharacteristic = (*env)->GetMethodID( @@ -970,7 +1145,7 @@ jobject CALEServerCreateGattService(JNIEnv *env) if (!jni_mid_bluetoothGattCharacteristic) { OIC_LOG(ERROR, TAG, "jni_mid_bluetoothGattCharacteristic is null"); - return NULL; + goto error_exit; } jobject jni_obj_serviceUUID = CALEGetUuidFromString(env, OIC_GATT_SERVICE_UUID); @@ -988,7 +1163,7 @@ jobject CALEServerCreateGattService(JNIEnv *env) if (!jni_bluetoothGattService) { OIC_LOG(ERROR, TAG, "jni_bluetoothGattService is null"); - return NULL; + goto error_exit; } jobject jni_obj_readUuid = CALEGetUuidFromString(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID); @@ -1001,14 +1176,17 @@ jobject CALEServerCreateGattService(JNIEnv *env) jint jni_int_readProperties = (*env)->GetStaticIntField(env, jni_cid_bluetoothGattCharacteristic, jni_fid_readProperties); + CACheckJNIException(env); jint jni_int_readPermissions = (*env)->GetStaticIntField(env, jni_cid_bluetoothGattCharacteristic, jni_fid_readPermissions); + CACheckJNIException(env); jint jni_int_writePermissions = (*env)->GetStaticIntField(env, jni_cid_bluetoothGattCharacteristic, jni_fid_writePermissions); + CACheckJNIException(env); jobject jni_readCharacteristic = (*env)->NewObject(env, jni_cid_bluetoothGattCharacteristic, jni_mid_bluetoothGattCharacteristic, @@ -1018,7 +1196,7 @@ jobject CALEServerCreateGattService(JNIEnv *env) if (!jni_readCharacteristic) { OIC_LOG(ERROR, TAG, "jni_readCharacteristic is null"); - return NULL; + goto error_exit; } jboolean jni_boolean_addReadCharacteristic = (*env)->CallBooleanMethod( @@ -1026,7 +1204,7 @@ jobject CALEServerCreateGattService(JNIEnv *env) if (!jni_boolean_addReadCharacteristic) { OIC_LOG(ERROR, TAG, "jni_boolean_addReadCharacteristic is null"); - return NULL; + goto error_exit; } jobject jni_obj_writeUuid = CALEGetUuidFromString(env, OIC_GATT_CHARACTERISTIC_REQUEST_UUID); @@ -1039,6 +1217,7 @@ jobject CALEServerCreateGattService(JNIEnv *env) jint jni_int_writeProperties = (*env)->GetStaticIntField(env, jni_cid_bluetoothGattCharacteristic, jni_fid_writeProperties); + CACheckJNIException(env); jobject jni_writeCharacteristic = (*env)->NewObject(env, jni_cid_bluetoothGattCharacteristic, jni_mid_bluetoothGattCharacteristic, @@ -1047,7 +1226,7 @@ jobject CALEServerCreateGattService(JNIEnv *env) if (!jni_writeCharacteristic) { OIC_LOG(ERROR, TAG, "jni_writeCharacteristic is null"); - return NULL; + goto error_exit; } jboolean jni_boolean_addWriteCharacteristic = (*env)->CallBooleanMethod( @@ -1055,11 +1234,15 @@ jobject CALEServerCreateGattService(JNIEnv *env) if (JNI_FALSE == jni_boolean_addWriteCharacteristic) { OIC_LOG(ERROR, TAG, "Fail to add jni_boolean_addReadCharacteristic"); - return NULL; + goto error_exit; } OIC_LOG(DEBUG, TAG, "OUT - CALEServerCreateGattService"); return jni_bluetoothGattService; + +error_exit: + CACheckJNIException(env); + return NULL; } CAResult_t CALEServerAddDescriptor(JNIEnv *env, jobject characteristic) @@ -1073,7 +1256,7 @@ CAResult_t CALEServerAddDescriptor(JNIEnv *env, jobject characteristic) if (!jni_cid_bluetoothGattDescriptor) { OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattDescriptor is null"); - return CA_STATUS_FAILED; + goto error_exit; } jmethodID jni_mid_bluetoothGattDescriptor = (*env)->GetMethodID(env, @@ -1083,7 +1266,7 @@ CAResult_t CALEServerAddDescriptor(JNIEnv *env, jobject characteristic) if (!jni_mid_bluetoothGattDescriptor) { OIC_LOG(ERROR, TAG, "jni_mid_bluetoothGattDescriptor is null"); - return CA_STATUS_FAILED; + goto error_exit; } jfieldID jni_fid_readPermissions = (*env)->GetStaticFieldID(env, @@ -1092,7 +1275,7 @@ CAResult_t CALEServerAddDescriptor(JNIEnv *env, jobject characteristic) if (!jni_fid_readPermissions) { OIC_LOG(ERROR, TAG, "jni_fid_readPermissions is null"); - return CA_STATUS_FAILED; + goto error_exit; } jobject jni_obj_readUuid = CALEGetUuidFromString(env, OIC_GATT_CHARACTERISTIC_CONFIG_UUID); @@ -1104,6 +1287,7 @@ CAResult_t CALEServerAddDescriptor(JNIEnv *env, jobject characteristic) jint jni_int_readPermissions = (*env)->GetStaticIntField(env, jni_cid_bluetoothGattDescriptor, jni_fid_readPermissions); + CACheckJNIException(env); OIC_LOG(DEBUG, TAG, "initialize new Descriptor"); @@ -1113,7 +1297,7 @@ CAResult_t CALEServerAddDescriptor(JNIEnv *env, jobject characteristic) if (!jni_readDescriptor) { OIC_LOG(ERROR, TAG, "jni_readDescriptor is null"); - return CA_STATUS_FAILED; + goto error_exit; } jclass jni_cid_GattCharacteristic = (*env)->FindClass(env, "android/bluetooth/" @@ -1121,7 +1305,7 @@ CAResult_t CALEServerAddDescriptor(JNIEnv *env, jobject characteristic) if (!jni_cid_GattCharacteristic) { OIC_LOG(ERROR, TAG, "jni_cid_GattCharacteristic is null"); - return CA_STATUS_FAILED; + goto error_exit; } jmethodID jni_mid_addDescriptor = (*env)->GetMethodID(env, jni_cid_GattCharacteristic, @@ -1131,7 +1315,7 @@ CAResult_t CALEServerAddDescriptor(JNIEnv *env, jobject characteristic) if (!jni_mid_addDescriptor) { OIC_LOG(ERROR, TAG, "jni_mid_addDescriptor is null"); - return CA_STATUS_FAILED; + goto error_exit; } jboolean jni_boolean_addDescriptor = (*env)->CallBooleanMethod(env, characteristic, @@ -1141,13 +1325,17 @@ CAResult_t CALEServerAddDescriptor(JNIEnv *env, jobject characteristic) if (JNI_FALSE == jni_boolean_addDescriptor) { OIC_LOG(ERROR, TAG, "addDescriptor has failed"); - return CA_STATUS_FAILED; + goto error_exit; } else { OIC_LOG(DEBUG, TAG, "addDescriptor success"); } return CA_STATUS_OK; + +error_exit: + CACheckJNIException(env); + return CA_STATUS_FAILED; } CAResult_t CALEServerAddGattService(JNIEnv *env, jobject bluetoothGattServer, @@ -1164,23 +1352,15 @@ CAResult_t CALEServerAddGattService(JNIEnv *env, jobject bluetoothGattServer, return CA_ADAPTER_NOT_ENABLED; } - jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env, - "android/bluetooth/BluetoothGattServer"); - if (!jni_cid_bluetoothGattServer) - { - OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null"); - return CA_STATUS_FAILED; - } - - jmethodID jni_mid_addService = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer, - "addService", - "(Landroid/bluetooth/BluetoothGattService;)" - "Z"); - if (!jni_mid_addService) - { - OIC_LOG(ERROR, TAG, "jni_mid_addService is null"); - return CA_STATUS_FAILED; - } + jmethodID jni_mid_addService = CAGetJNIMethodID(env, CLASSPATH_BT_GATTSERVER, + "addService", + "(Landroid/bluetooth/BluetoothGattService;)" + "Z"); + if (!jni_mid_addService) + { + OIC_LOG(ERROR, TAG, "jni_mid_addService is null"); + return CA_STATUS_FAILED; + } jboolean jni_boolean_addService = (*env)->CallBooleanMethod(env, bluetoothGattServer, jni_mid_addService, @@ -1189,6 +1369,7 @@ CAResult_t CALEServerAddGattService(JNIEnv *env, jobject bluetoothGattServer, if (JNI_FALSE == jni_boolean_addService) { OIC_LOG(ERROR, TAG, "Fail to add GATT service"); + CACheckJNIException(env); return CA_STATUS_FAILED; } @@ -1208,16 +1389,9 @@ CAResult_t CALEServerConnect(JNIEnv *env, jobject bluetoothDevice) return CA_ADAPTER_NOT_ENABLED; } - jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env, - "android/bluetooth/BluetoothGattServer"); - if (!jni_cid_bluetoothGattServer) - { - OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null"); - return CA_STATUS_FAILED; - } - - jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer, "connect", - "(Landroid/bluetooth/BluetoothDevice;Z)Z"); + jmethodID jni_mid_connect = CAGetJNIMethodID(env, CLASSPATH_BT_GATTSERVER, + "connect", + "(Landroid/bluetooth/BluetoothDevice;Z)Z"); if (!jni_mid_connect) { OIC_LOG(ERROR, TAG, "jni_mid_connect is null"); @@ -1230,6 +1404,7 @@ CAResult_t CALEServerConnect(JNIEnv *env, jobject bluetoothDevice) if (JNI_FALSE == jni_boolean_connect) { OIC_LOG(ERROR, TAG, "Fail to connect"); + CACheckJNIException(env); return CA_STATUS_FAILED; } @@ -1242,11 +1417,11 @@ CAResult_t CALEServerDisconnectAllDevices(JNIEnv *env) OIC_LOG(DEBUG, TAG, "IN - CALEServerDisconnectAllDevices"); VERIFY_NON_NULL(env, TAG, "env is null"); - ca_mutex_lock(g_connectedDeviceListMutex); + oc_mutex_lock(g_connectedDeviceListMutex); if (!g_connectedDeviceList) { OIC_LOG(ERROR, TAG, "g_connectedDeviceList is null"); - ca_mutex_unlock(g_connectedDeviceListMutex); + oc_mutex_unlock(g_connectedDeviceListMutex); return CA_STATUS_FAILED; } @@ -1269,7 +1444,7 @@ CAResult_t CALEServerDisconnectAllDevices(JNIEnv *env) } } - ca_mutex_unlock(g_connectedDeviceListMutex); + oc_mutex_unlock(g_connectedDeviceListMutex); OIC_LOG(DEBUG, TAG, "OUT - CALEServerDisconnectAllDevices"); return CA_STATUS_OK; } @@ -1286,18 +1461,10 @@ CAResult_t CALEServerDisconnect(JNIEnv *env, jobject bluetoothDevice) return CA_ADAPTER_NOT_ENABLED; } - jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env, - "android/bluetooth/BluetoothGattServer"); - if (!jni_cid_bluetoothGattServer) - { - OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null"); - return CA_STATUS_FAILED; - } - - jmethodID jni_mid_cancelConnection = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer, - "cancelConnection", - "(Landroid/bluetooth/BluetoothDevice;)" - "V"); + jmethodID jni_mid_cancelConnection = CAGetJNIMethodID(env, CLASSPATH_BT_GATTSERVER, + "cancelConnection", + "(Landroid/bluetooth/BluetoothDevice;)" + "V"); if (!jni_mid_cancelConnection) { OIC_LOG(ERROR, TAG, "jni_mid_cancelConnection is null"); @@ -1306,11 +1473,9 @@ CAResult_t CALEServerDisconnect(JNIEnv *env, jobject bluetoothDevice) (*env)->CallVoidMethod(env, g_bluetoothGattServer, jni_mid_cancelConnection, bluetoothDevice); - if ((*env)->ExceptionCheck(env)) + if (CACheckJNIException(env)) { OIC_LOG(ERROR, TAG, "cancelConnection has failed"); - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); return CA_STATUS_FAILED; } @@ -1327,14 +1492,8 @@ CAResult_t CALEServerGattClose(JNIEnv *env, jobject bluetoothGattServer) // get BluetoothGatt class OIC_LOG(DEBUG, TAG, "get BluetoothGatt class"); - jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, "android/bluetooth/BluetoothGattServer"); - if (!jni_cid_BluetoothGatt) - { - OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null"); - return CA_STATUS_FAILED; - } - - jmethodID jni_mid_closeGatt = (*env)->GetMethodID(env, jni_cid_BluetoothGatt, "close", "()V"); + jmethodID jni_mid_closeGatt = CAGetJNIMethodID(env, CLASSPATH_BT_GATTSERVER, + "close", "()V"); if (!jni_mid_closeGatt) { OIC_LOG(ERROR, TAG, "jni_mid_closeGatt is null"); @@ -1345,11 +1504,9 @@ CAResult_t CALEServerGattClose(JNIEnv *env, jobject bluetoothGattServer) OIC_LOG(DEBUG, TAG, "request to close GATT"); (*env)->CallVoidMethod(env, bluetoothGattServer, jni_mid_closeGatt); - if ((*env)->ExceptionCheck(env)) + if (CACheckJNIException(env)) { OIC_LOG(ERROR, TAG, "closeGATT has failed"); - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); return CA_STATUS_FAILED; } @@ -1400,7 +1557,7 @@ CAResult_t CALEServerInitialize() } bool isAttached = false; - JNIEnv* env; + JNIEnv* env = NULL; jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { @@ -1427,6 +1584,8 @@ CAResult_t CALEServerInitialize() return ret; } + g_threadSendNotifyCond = oc_cond_new(); + ret = CALEServerInitMutexVaraibles(); if (CA_STATUS_OK != ret) { @@ -1468,11 +1627,53 @@ void CALEServerTerminate() { OIC_LOG(DEBUG, TAG, "IN - CALEServerTerminate"); + if (!g_jvm) + { + OIC_LOG(ERROR, TAG, "g_jvm is null"); + return; + } + + bool isAttached = false; + JNIEnv* env = NULL; + jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); + if (JNI_OK != res) + { + OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer"); + res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); + + if (JNI_OK != res) + { + OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed"); + return; + } + isAttached = true; + } + + if (g_sendBuffer) + { + (*env)->DeleteGlobalRef(env, g_sendBuffer); + g_sendBuffer = NULL; + } + + if (g_bluetoothManager) + { + (*env)->DeleteGlobalRef(env, g_bluetoothManager); + g_bluetoothManager = NULL; + } + + oc_cond_free(g_threadSendNotifyCond); + g_threadSendNotifyCond = NULL; + CALEServerTerminateMutexVaraibles(); CALEServerTerminateConditionVaraibles(); g_isInitializedServer = false; + if (isAttached) + { + (*g_jvm)->DetachCurrentThread(g_jvm); + } + OIC_LOG(DEBUG, TAG, "OUT - CALEServerTerminate"); } @@ -1489,7 +1690,7 @@ CAResult_t CALEServerSendUnicastMessage(const char* address, const uint8_t* data } bool isAttached = false; - JNIEnv* env; + JNIEnv* env = NULL; jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { @@ -1530,7 +1731,7 @@ CAResult_t CALEServerSendMulticastMessage(const uint8_t* data, uint32_t dataLen) } bool isAttached = false; - JNIEnv* env; + JNIEnv* env = NULL; jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { @@ -1582,7 +1783,7 @@ CAResult_t CALEServerStartMulticastServer() } bool isAttached = false; - JNIEnv* env; + JNIEnv* env = NULL; jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { @@ -1608,12 +1809,16 @@ CAResult_t CALEServerStartMulticastServer() } // start advertise - ret = CALEServerStartAdvertise(env, g_leAdvertiseCallback); + ret = CALEServerStartAdvertise(); if (CA_STATUS_OK != ret) { OIC_LOG(ERROR, TAG, "CALEServerStartAdvertise has failed"); } + // get Constants Value from Android Platform + g_state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED"); + g_state_disconnected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_DISCONNECTED"); + if (isAttached) { (*g_jvm)->DetachCurrentThread(g_jvm); @@ -1633,29 +1838,7 @@ CAResult_t CALEServerStopMulticastServer() return CA_STATUS_FAILED; } - if (!g_jvm) - { - OIC_LOG(ERROR, TAG, "g_jvm is null"); - return CA_STATUS_FAILED; - } - - bool isAttached = false; - JNIEnv* env; - jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); - if (JNI_OK != res) - { - OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer"); - res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); - - if (JNI_OK != res) - { - OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed"); - return CA_STATUS_FAILED; - } - isAttached = true; - } - - CAResult_t ret = CALEServerStopAdvertise(env, g_leAdvertiseCallback); + CAResult_t ret = CALEServerStopAdvertise(); if (CA_STATUS_OK != ret) { OIC_LOG(ERROR, TAG, "CALEServerStopAdvertise has failed"); @@ -1663,11 +1846,6 @@ CAResult_t CALEServerStopMulticastServer() g_isStartServer = false; - if (isAttached) - { - (*g_jvm)->DetachCurrentThread(g_jvm); - } - OIC_LOG(DEBUG, TAG, "OUT - CALEServerStopMulticastServer"); return ret; } @@ -1693,7 +1871,8 @@ CAResult_t CALEServerSendUnicastMessageImpl(JNIEnv *env, const char* address, co return CA_STATUS_FAILED; } - jobject jni_obj_bluetoothDevice = NULL; + oc_mutex_lock(g_threadSendMutex); + uint32_t length = u_arraylist_length(g_connectedDeviceList); for (uint32_t index = 0; index < length; index++) { @@ -1702,54 +1881,93 @@ CAResult_t CALEServerSendUnicastMessageImpl(JNIEnv *env, const char* address, co if (!jarrayObj) { OIC_LOG(ERROR, TAG, "jarrayObj is null"); - return CA_STATUS_FAILED; + goto error_exit; } jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj); if (!jni_setAddress) { OIC_LOG(ERROR, TAG, "jni_setAddress is null"); - return CA_STATUS_FAILED; + goto error_exit; } const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL); if (!setAddress) { OIC_LOG(ERROR, TAG, "setAddress is null"); - return CA_STATUS_FAILED; + goto error_exit; } OIC_LOG_V(DEBUG, TAG, "setAddress : %s", setAddress); OIC_LOG_V(DEBUG, TAG, "address : %s", address); - if (!strcmp(setAddress, address)) + if (!strcasecmp(setAddress, address)) { OIC_LOG(DEBUG, TAG, "found the device"); - jni_obj_bluetoothDevice = jarrayObj; + + if (g_obj_bluetoothDevice) + { + (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice); + g_obj_bluetoothDevice = NULL; + } + + if (jarrayObj) + { + g_obj_bluetoothDevice = (*env)->NewGlobalRef(env, jarrayObj); + CACheckJNIException(env); + } (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); break; } (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); } - if (jni_obj_bluetoothDevice) + if (g_obj_bluetoothDevice) { - jbyteArray jni_bytearr_data = (*env)->NewByteArray(env, dataLen); - (*env)->SetByteArrayRegion(env, jni_bytearr_data, 0, dataLen, (jbyte*) data); + jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen); + CACheckJNIException(env); + (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data); + CACheckJNIException(env); + g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr); + CACheckJNIException(env); - CAResult_t res = CALEServerSend(env, jni_obj_bluetoothDevice, jni_bytearr_data); + CAResult_t res = CALEServerSend(env, g_obj_bluetoothDevice, g_sendBuffer); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "send has failed"); - return CA_SEND_FAILED; + goto error_exit; } } else { OIC_LOG(ERROR, TAG, "There are no device to send in the list"); - return CA_STATUS_FAILED; + goto error_exit; } + if (g_sendBuffer) + { + (*env)->DeleteGlobalRef(env, g_sendBuffer); + g_sendBuffer = NULL; + } + + oc_mutex_unlock(g_threadSendMutex); + OIC_LOG(INFO, TAG, "unicast - send request is successful"); return CA_STATUS_OK; + +error_exit: + if (g_sendBuffer) + { + (*env)->DeleteGlobalRef(env, g_sendBuffer); + g_sendBuffer = NULL; + } + + if (g_obj_bluetoothDevice) + { + (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice); + g_obj_bluetoothDevice = NULL; + } + + oc_mutex_unlock(g_threadSendMutex); + return CA_SEND_FAILED; } CAResult_t CALEServerSendMulticastMessageImpl(JNIEnv *env, const uint8_t *data, uint32_t dataLen) @@ -1764,6 +1982,21 @@ CAResult_t CALEServerSendMulticastMessageImpl(JNIEnv *env, const uint8_t *data, return CA_STATUS_FAILED; } + oc_mutex_lock(g_threadSendMutex); + + OIC_LOG(DEBUG, TAG, "set data into g_sendBuffer for notify"); + if (g_sendBuffer) + { + (*env)->DeleteGlobalRef(env, g_sendBuffer); + g_sendBuffer = NULL; + } + jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen); + CACheckJNIException(env); + (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data); + CACheckJNIException(env); + g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr); + CACheckJNIException(env); + uint32_t length = u_arraylist_length(g_connectedDeviceList); for (uint32_t index = 0; index < length; index++) { @@ -1771,33 +2004,87 @@ CAResult_t CALEServerSendMulticastMessageImpl(JNIEnv *env, const uint8_t *data, if (!jarrayObj) { OIC_LOG(ERROR, TAG, "jarrayObj is null"); - return CA_STATUS_FAILED; + continue; } // send data for all device jbyteArray jni_bytearr_data = (*env)->NewByteArray(env, dataLen); + CACheckJNIException(env); (*env)->SetByteArrayRegion(env, jni_bytearr_data, 0, dataLen, (jbyte*) data); - CAResult_t res = CALEServerSend(env, jarrayObj, jni_bytearr_data); + CACheckJNIException(env); + + jstring jni_address = CALEGetAddressFromBTDevice(env, jarrayObj); + if (!jni_address) + { + OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed"); + continue; + } + + const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL); + if (!address) + { + OIC_LOG(ERROR, TAG, "address is not available"); + continue; + } + + if (g_obj_bluetoothDevice) + { + (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice); + g_obj_bluetoothDevice = NULL; + } + + if (jarrayObj) + { + g_obj_bluetoothDevice = (*env)->NewGlobalRef(env, jarrayObj); + CACheckJNIException(env); + } + + CAResult_t res = CALEServerSend(env, g_obj_bluetoothDevice, jni_bytearr_data); if (CA_STATUS_OK != res) { - OIC_LOG(ERROR, TAG, "send has failed"); - return CA_SEND_FAILED; + OIC_LOG_V(ERROR, TAG, "send has failed for the device[%s]", address); + (*env)->ReleaseStringUTFChars(env, jni_address, address); + if (g_obj_bluetoothDevice) + { + (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice); + g_obj_bluetoothDevice = NULL; + } + continue; } + + OIC_LOG_V(INFO, TAG, "unicast - send request is successful for a device[%s]", address); + (*env)->ReleaseStringUTFChars(env, jni_address, address); } + if (g_sendBuffer) + { + (*env)->DeleteGlobalRef(env, g_sendBuffer); + g_sendBuffer = NULL; + } + + oc_mutex_unlock(g_threadSendMutex); return CA_STATUS_OK; } void CALEServerCreateCachedDeviceList() { - ca_mutex_lock(g_connectedDeviceListMutex); + oc_mutex_lock(g_connectedDeviceListMutex); // create new object array if (!g_connectedDeviceList) { OIC_LOG(DEBUG, TAG, "Create device list"); g_connectedDeviceList = u_arraylist_create(); } - ca_mutex_unlock(g_connectedDeviceListMutex); + oc_mutex_unlock(g_connectedDeviceListMutex); + + oc_mutex_lock(g_deviceStateListMutex); + // create new object array + if (!g_deviceStateList) + { + OIC_LOG(DEBUG, TAG, "Create device list"); + g_deviceStateList = u_arraylist_create(); + } + oc_mutex_unlock(g_deviceStateListMutex); } bool CALEServerIsDeviceInList(JNIEnv *env, const char* remoteAddress) @@ -1836,7 +2123,7 @@ bool CALEServerIsDeviceInList(JNIEnv *env, const char* remoteAddress) return false; } - if (!strcmp(remoteAddress, setAddress)) + if (!strcasecmp(remoteAddress, setAddress)) { OIC_LOG(ERROR, TAG, "the device is already set"); (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); @@ -1859,12 +2146,12 @@ CAResult_t CALEServerAddDeviceToList(JNIEnv *env, jobject device) VERIFY_NON_NULL(device, TAG, "device is null"); VERIFY_NON_NULL(env, TAG, "env is null"); - ca_mutex_lock(g_connectedDeviceListMutex); + oc_mutex_lock(g_connectedDeviceListMutex); if (!g_connectedDeviceList) { OIC_LOG(ERROR, TAG, "list is null"); - ca_mutex_unlock(g_connectedDeviceListMutex); + oc_mutex_unlock(g_connectedDeviceListMutex); return CA_STATUS_FAILED; } @@ -1872,7 +2159,7 @@ CAResult_t CALEServerAddDeviceToList(JNIEnv *env, jobject device) if (!jni_remoteAddress) { OIC_LOG(ERROR, TAG, "jni_remoteAddress is null"); - ca_mutex_unlock(g_connectedDeviceListMutex); + oc_mutex_unlock(g_connectedDeviceListMutex); return CA_STATUS_FAILED; } @@ -1880,7 +2167,7 @@ CAResult_t CALEServerAddDeviceToList(JNIEnv *env, jobject device) if (!remoteAddress) { OIC_LOG(ERROR, TAG, "remoteAddress is null"); - ca_mutex_unlock(g_connectedDeviceListMutex); + oc_mutex_unlock(g_connectedDeviceListMutex); return CA_STATUS_FAILED; } @@ -1892,7 +2179,7 @@ CAResult_t CALEServerAddDeviceToList(JNIEnv *env, jobject device) } (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress); - ca_mutex_unlock(g_connectedDeviceListMutex); + oc_mutex_unlock(g_connectedDeviceListMutex); OIC_LOG(DEBUG, TAG, "OUT - CALEServerAddDeviceToList"); return CA_STATUS_OK; } @@ -1902,11 +2189,11 @@ CAResult_t CALEServerRemoveAllDevices(JNIEnv *env) OIC_LOG(DEBUG, TAG, "IN - CALEServerRemoveAllDevices"); VERIFY_NON_NULL(env, TAG, "env is null"); - ca_mutex_lock(g_connectedDeviceListMutex); + oc_mutex_lock(g_connectedDeviceListMutex); if (!g_connectedDeviceList) { OIC_LOG(ERROR, TAG, "g_connectedDeviceList is null"); - ca_mutex_unlock(g_connectedDeviceListMutex); + oc_mutex_unlock(g_connectedDeviceListMutex); return CA_STATUS_FAILED; } @@ -1922,7 +2209,7 @@ CAResult_t CALEServerRemoveAllDevices(JNIEnv *env) OICFree(g_connectedDeviceList); g_connectedDeviceList = NULL; - ca_mutex_unlock(g_connectedDeviceListMutex); + oc_mutex_unlock(g_connectedDeviceListMutex); OIC_LOG(DEBUG, TAG, "OUT - CALEServerRemoveAllDevices"); return CA_STATUS_OK; @@ -1934,11 +2221,11 @@ CAResult_t CALEServerRemoveDevice(JNIEnv *env, jstring address) VERIFY_NON_NULL(env, TAG, "env is null"); VERIFY_NON_NULL(address, TAG, "address is null"); - ca_mutex_lock(g_connectedDeviceListMutex); + oc_mutex_lock(g_connectedDeviceListMutex); if (!g_connectedDeviceList) { OIC_LOG(ERROR, TAG, "no deviceList"); - ca_mutex_unlock(g_connectedDeviceListMutex); + oc_mutex_unlock(g_connectedDeviceListMutex); return CA_STATUS_FAILED; } @@ -1970,21 +2257,22 @@ CAResult_t CALEServerRemoveDevice(JNIEnv *env, jstring address) continue; } - if (!strcmp(setAddress, remoteAddress)) + if (!strcasecmp(setAddress, remoteAddress)) { OIC_LOG_V(DEBUG, TAG, "device address : %s", remoteAddress); (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); (*env)->ReleaseStringUTFChars(env, address, remoteAddress); (*env)->DeleteGlobalRef(env, jarrayObj); + jarrayObj = NULL; if (NULL == u_arraylist_remove(g_connectedDeviceList, index)) { OIC_LOG(ERROR, TAG, "List removal failed."); - ca_mutex_unlock(g_connectedDeviceListMutex); + oc_mutex_unlock(g_connectedDeviceListMutex); return CA_STATUS_FAILED; } - ca_mutex_unlock(g_connectedDeviceListMutex); + oc_mutex_unlock(g_connectedDeviceListMutex); return CA_STATUS_OK; } (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); @@ -1992,7 +2280,7 @@ CAResult_t CALEServerRemoveDevice(JNIEnv *env, jstring address) } } - ca_mutex_unlock(g_connectedDeviceListMutex); + oc_mutex_unlock(g_connectedDeviceListMutex); OIC_LOG(DEBUG, TAG, "there are no device in the device list"); @@ -2010,6 +2298,7 @@ Java_org_iotivity_ca_CaLeServerInterface_caLeRegisterGattServerCallback(JNIEnv * VERIFY_NON_NULL_VOID(callback, TAG, "callback"); g_bluetoothGattServerCallback = (*env)->NewGlobalRef(env, callback); + CACheckJNIException(env); } JNIEXPORT void JNICALL @@ -2023,6 +2312,7 @@ Java_org_iotivity_ca_CaLeServerInterface_caLeRegisterBluetoothLeAdvertiseCallbac VERIFY_NON_NULL_VOID(callback, TAG, "callback"); g_leAdvertiseCallback = (*env)->NewGlobalRef(env, callback); + CACheckJNIException(env); } JNIEXPORT void JNICALL @@ -2036,86 +2326,85 @@ Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerConnectionStateChangeCall VERIFY_NON_NULL_VOID(obj, TAG, "obj"); VERIFY_NON_NULL_VOID(device, TAG, "device"); - jclass jni_cid_bluetoothProfile = (*env)->FindClass(env, "android/bluetooth/BluetoothProfile"); - if (!jni_cid_bluetoothProfile) - { - OIC_LOG(ERROR, TAG, "jni_cid_bluetoothProfile is null"); - return; - } - - jfieldID jni_fid_state_connected = (*env)->GetStaticFieldID(env, jni_cid_bluetoothProfile, - "STATE_CONNECTED", "I"); - if(!jni_fid_state_connected) + jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device); + if (!jni_remoteAddress) { - OIC_LOG(ERROR, TAG, "jni_fid_state_connected is null"); + OIC_LOG(ERROR, TAG, "jni_remoteAddress is null"); return; } - jfieldID jni_fid_state_disconnected = (*env)->GetStaticFieldID(env, jni_cid_bluetoothProfile, - "STATE_DISCONNECTED", "I"); - if(!jni_fid_state_disconnected) + const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL); + if (!remoteAddress) { - OIC_LOG(ERROR, TAG, "jni_fid_state_disconnected is null"); + OIC_LOG(ERROR, TAG, "remoteAddress is null"); + CACheckJNIException(env); return; } - // STATE_CONNECTED - jint jni_int_state_connected = (*env)->GetStaticIntField(env, jni_cid_bluetoothProfile, - jni_fid_state_connected); - - // STATE_DISCONNECTED - jint jni_int_state_disconnected = (*env)->GetStaticIntField(env, jni_cid_bluetoothProfile, - jni_fid_state_disconnected); - - if (newState == jni_int_state_connected) + if (newState == g_state_connected) { - OIC_LOG(DEBUG, TAG, "LE CONNECTED"); - jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device); - if (!jni_remoteAddress) + if (false == CALEServerIsDeviceInList(env, remoteAddress)) { - OIC_LOG(ERROR, TAG, "jni_remoteAddress is null"); - return; + OIC_LOG(DEBUG, TAG, "add connected device to cache"); + CALEServerAddDeviceToList(env, device); } - const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL); - if (!remoteAddress) + CAResult_t res = CALEUpdateDeviceState(remoteAddress, + CA_LE_CONNECTION_STATE, + STATE_CONNECTED, + g_deviceStateList, + g_deviceStateListMutex); + if (CA_STATUS_OK != res) { - OIC_LOG(ERROR, TAG, "remoteAddress is null"); - return; + OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed"); } - if (false == CALEServerIsDeviceInList(env, remoteAddress)) + res = CALEServerStopAdvertise(); + if (CA_STATUS_OK != res) { - OIC_LOG(DEBUG, TAG, "add connected device to cache"); - CALEServerAddDeviceToList(env, device); + OIC_LOG(DEBUG, TAG, "CALEServerStopAdvertise has failed"); } - (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress); } - else if (newState == jni_int_state_disconnected) + else if (newState == g_state_disconnected) { OIC_LOG(DEBUG, TAG, "LE DISCONNECTED"); jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device); - CAResult_t ret = CALEServerRemoveDevice(env, jni_remoteAddress); - if (CA_STATUS_OK != ret) + CAResult_t res = CALEServerRemoveDevice(env, jni_remoteAddress); + if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "CALEServerRemoveDevice has failed"); } + res = CALEUpdateDeviceState(remoteAddress, + CA_LE_CONNECTION_STATE, + STATE_DISCONNECTED, + g_deviceStateList, + g_deviceStateListMutex); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed"); + } + // start advertise - ret = CALEServerStartAdvertise(env, g_leAdvertiseCallback); - if (CA_STATUS_OK != ret) + res = CALEServerStartAdvertise(); + if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "CALEServerStartAdvertise has failed"); } } else { +#ifndef TB_LOG + (void)status; +#endif OIC_LOG_V(DEBUG, TAG, "LE Connection state is [newState : %d, status %d]", newState, status); } + (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress); + (*env)->DeleteLocalRef(env, jni_remoteAddress); } JNIEXPORT void JNICALL @@ -2127,7 +2416,9 @@ Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerServiceAddedCallback(JNIE VERIFY_NON_NULL_VOID(env, TAG, "env"); VERIFY_NON_NULL_VOID(obj, TAG, "obj"); VERIFY_NON_NULL_VOID(gattService, TAG, "gattService"); - +#ifndef TB_LOG + (void)status; +#endif OIC_LOG_V(DEBUG, TAG, "Gatt Service Added Callback(%d)", status); } @@ -2144,7 +2435,8 @@ Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerCharacteristicReadRequest JNIEXPORT void JNICALL Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerCharacteristicWriteRequestCallback( - JNIEnv *env, jobject obj, jobject device, jbyteArray data) + JNIEnv *env, jobject obj, jobject device, jbyteArray data, + jint requestId, jint offset, jbyteArray value) { OIC_LOG_V(DEBUG, TAG, "Gatt Server Characteristic Write Request Callback"); VERIFY_NON_NULL_VOID(env, TAG, "env"); @@ -2152,11 +2444,24 @@ Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerCharacteristicWriteReques VERIFY_NON_NULL_VOID(device, TAG, "device"); VERIFY_NON_NULL_VOID(data, TAG, "data"); + if (g_setHighQoS) + { + CALEServerSendResponse(env, device, requestId, 0, offset, value); + } + else + { + (void)requestId; + (void)offset; + (void)value; + } + // get Byte Array and covert to uint8_t* jint length = (*env)->GetArrayLength(env, data); + CACheckJNIException(env); jboolean isCopy; jbyte *jni_byte_requestData = (jbyte *) (*env)->GetByteArrayElements(env, data, &isCopy); + CACheckJNIException(env); uint8_t* requestData = NULL; requestData = OICMalloc(length); @@ -2181,17 +2486,18 @@ Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerCharacteristicWriteReques if (!address) { OIC_LOG(ERROR, TAG, "address is null"); + CACheckJNIException(env); OICFree(requestData); return; } OIC_LOG_V(DEBUG, TAG, "remote device address : %s, %p, %d", address, requestData, length); - ca_mutex_lock(g_bleClientBDAddressMutex); + oc_mutex_lock(g_bleClientBDAddressMutex); uint32_t sentLength = 0; g_CABLEServerDataReceivedCallback(address, requestData, length, &sentLength); - ca_mutex_unlock(g_bleClientBDAddressMutex); + oc_mutex_unlock(g_bleClientBDAddressMutex); (*env)->ReleaseStringUTFChars(env, jni_address, address); } @@ -2206,8 +2512,76 @@ Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerNotificationSentCallback( VERIFY_NON_NULL_VOID(obj, TAG, "obj"); VERIFY_NON_NULL_VOID(device, TAG, "device"); - OIC_LOG_V(DEBUG, TAG, "Gatt Server Notification Sent Callback(%d)", + OIC_LOG_V(DEBUG, TAG, "Gatt Server Notification Sent Callback (status : %d)", status); + + jstring jni_address = CALEGetAddressFromBTDevice(env, device); + if (!jni_address) + { + OIC_LOG(ERROR, TAG, "jni_address is null"); + return; + } + + const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL); + if (!address) + { + OIC_LOG(ERROR, TAG, "address is not available"); + (*env)->DeleteLocalRef(env, jni_address); + return; + } + + jint gatt_success = CALEGetConstantsValue(env, CLASSPATH_BT_GATT, "GATT_SUCCESS"); + if (gatt_success != status) // error case + { + OIC_LOG(ERROR, TAG, "it will be sent again."); + + CAResult_t res = CALEServerSend(env, device, g_sendBuffer); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "send has failed"); + + if (g_obj_bluetoothDevice) + { + (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice); + g_obj_bluetoothDevice = NULL; + } + + oc_mutex_lock(g_threadSendNotifyMutex); + g_isSignalSetFlag = true; + oc_cond_signal(g_threadSendNotifyCond); + oc_mutex_unlock(g_threadSendNotifyMutex); + + (*env)->ReleaseStringUTFChars(env, jni_address, address); + (*env)->DeleteLocalRef(env, jni_address); + return; + } + + CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, address, 0, -1, + false, "notifyChar failure"); + } + else + { + OIC_LOG(DEBUG, TAG, "notify success"); + + if (g_obj_bluetoothDevice) + { + (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice); + g_obj_bluetoothDevice = NULL; + } + + // next data can be sent + oc_mutex_lock(g_threadSendNotifyMutex); + OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal"); + g_isSignalSetFlag = true; + oc_cond_signal(g_threadSendNotifyCond); + oc_mutex_unlock(g_threadSendNotifyMutex); + + CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, address, 0, -1, + true, "notifyChar success"); + } + (*env)->ReleaseStringUTFChars(env, jni_address, address); + (*env)->DeleteLocalRef(env, jni_address); + } JNIEXPORT void JNICALL @@ -2231,6 +2605,68 @@ Java_org_iotivity_ca_CaLeServerInterface_caLeAdvertiseStartFailureCallback(JNIEn VERIFY_NON_NULL_VOID(obj, TAG, "obj"); OIC_LOG_V(INFO, TAG, "LE Advertise Start Failure Callback(%d)", errorCode); + + jint data_too_large = CALEGetConstantsValue(env, CLASSPATH_BT_ADVERTISE_CB, + "ADVERTISE_FAILED_DATA_TOO_LARGE"); + jint already_started = CALEGetConstantsValue(env, CLASSPATH_BT_ADVERTISE_CB, + "ADVERTISE_FAILED_ALREADY_STARTED"); + + if (data_too_large == errorCode) + { + OIC_LOG_V(ERROR, TAG, "advertise data too large. please check length of device name"); + } + else if (already_started == errorCode) + { + OIC_LOG_V(INFO, TAG, "advertising is already started"); + } +} + +JNIEXPORT void JNICALL +Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerMtuChangedCallback(JNIEnv * env, + jobject obj, + jobject device, + jint mtu) +{ + VERIFY_NON_NULL_VOID(env, TAG, "env"); + VERIFY_NON_NULL_VOID(obj, TAG, "obj"); + VERIFY_NON_NULL_VOID(device, TAG, "device"); + + OIC_LOG_V(INFO, TAG, "gatt MTU size is changed (%d byte)", mtu); + + jstring jni_address = CALEGetAddressFromBTDevice(env, device); + if (!jni_address) + { + OIC_LOG(ERROR, TAG, "jni_address is null"); + return; + } + + const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL); + if (!address) + { + OIC_LOG(ERROR, TAG, "address is not available"); + (*env)->DeleteLocalRef(env, jni_address); + return; + } + + // update mtu size + CAResult_t res = CALESetMtuSize(address, mtu - CA_BLE_MTU_HEADER_SIZE, + g_deviceStateList, g_deviceStateListMutex); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "CALESetMtuSize has failed"); + } + + res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE, + STATE_SEND_MTU_NEGO_SUCCESS, + g_deviceStateList, + g_deviceStateListMutex); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed"); + } + + (*env)->ReleaseStringUTFChars(env, jni_address, address); + (*env)->DeleteLocalRef(env, jni_address); } /** @@ -2256,7 +2692,7 @@ CAResult_t CAStopLEGattServer() } bool isAttached = false; - JNIEnv* env; + JNIEnv* env = NULL; jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { @@ -2314,6 +2750,16 @@ CAResult_t CAStopLEGattServer() (*env)->DeleteGlobalRef(env, g_bluetoothGattServerCallback); } + if (g_obj_bluetoothDevice) + { + (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice); + g_obj_bluetoothDevice = NULL; + } + + oc_mutex_lock(g_threadSendNotifyMutex); + oc_cond_signal(g_threadSendNotifyCond); + oc_mutex_unlock(g_threadSendNotifyMutex); + g_isStartServer = false; if (isAttached) @@ -2338,9 +2784,9 @@ void CATerminateLEGattServer() void CASetLEReqRespServerCallback(CABLEDataReceivedCallback callback) { - ca_mutex_lock(g_bleReqRespCbMutex); + oc_mutex_lock(g_bleReqRespCbMutex); g_CABLEServerDataReceivedCallback = callback; - ca_mutex_unlock(g_bleReqRespCbMutex); + oc_mutex_unlock(g_bleReqRespCbMutex); } void CASetBLEServerErrorHandleCallback(CABLEErrorHandleCallback callback) @@ -2377,36 +2823,67 @@ CAResult_t CAUpdateCharacteristicsToAllGattClients(const uint8_t *charValue, void CASetLEServerThreadPoolHandle(ca_thread_pool_t handle) { OIC_LOG(INFO, TAG, "CASetLEServerThreadPoolHandle is not support"); + (void)handle; } CAResult_t CALEServerInitMutexVaraibles() { if (NULL == g_bleReqRespCbMutex) { - g_bleReqRespCbMutex = ca_mutex_new(); + g_bleReqRespCbMutex = oc_mutex_new(); if (NULL == g_bleReqRespCbMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } if (NULL == g_bleClientBDAddressMutex) { - g_bleClientBDAddressMutex = ca_mutex_new(); + g_bleClientBDAddressMutex = oc_mutex_new(); if (NULL == g_bleClientBDAddressMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } if (NULL == g_connectedDeviceListMutex) { - g_connectedDeviceListMutex = ca_mutex_new(); + g_connectedDeviceListMutex = oc_mutex_new(); if (NULL == g_connectedDeviceListMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_threadSendMutex) + { + g_threadSendMutex = oc_mutex_new(); + if (NULL == g_threadSendMutex) + { + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_threadSendNotifyMutex) + { + g_threadSendNotifyMutex = oc_mutex_new(); + if (NULL == g_threadSendNotifyMutex) + { + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_deviceStateListMutex) + { + g_deviceStateListMutex = oc_mutex_new(); + if (NULL == g_deviceStateListMutex) + { + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } @@ -2416,17 +2893,46 @@ CAResult_t CALEServerInitMutexVaraibles() void CALEServerTerminateMutexVaraibles() { - ca_mutex_free(g_bleReqRespCbMutex); + oc_mutex_free(g_bleReqRespCbMutex); g_bleReqRespCbMutex = NULL; - ca_mutex_free(g_bleClientBDAddressMutex); + oc_mutex_free(g_bleClientBDAddressMutex); g_bleClientBDAddressMutex = NULL; - ca_mutex_free(g_connectedDeviceListMutex); + oc_mutex_free(g_connectedDeviceListMutex); g_connectedDeviceListMutex = NULL; + + oc_mutex_free(g_threadSendMutex); + g_threadSendMutex = NULL; + + oc_mutex_free(g_threadSendNotifyMutex); + g_threadSendNotifyMutex = NULL; + + oc_mutex_free(g_deviceStateListMutex); + g_deviceStateListMutex = NULL; } void CALEServerTerminateConditionVaraibles() { OIC_LOG(DEBUG, TAG, "this method is not supported"); } + +bool CALEServerIsConnected(const char* address) +{ + if (CALEIsValidState(address, CA_LE_CONNECTION_STATE, + STATE_SERVICE_CONNECTED, + g_deviceStateList, + g_deviceStateListMutex)) + { + OIC_LOG(DEBUG, TAG, "current state is connected"); + return true; + } + OIC_LOG(DEBUG, TAG, "current state is not connected"); + return false; +} + +uint16_t CALEServerGetMtuSize(const char* address) +{ + return CALEGetMtuSize(address, g_deviceStateList, g_deviceStateListMutex); +} +