X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;ds=sidebyside;f=resource%2Fcsdk%2Fconnectivity%2Fsrc%2Fbt_edr_adapter%2Fandroid%2Fcaedrclient.c;h=5ff9200da962ccad3a6327e7311720703d75b9e3;hb=075e7cf10b7f5e3cf1f2afbbc6c5d2d7c4a17005;hp=f633632f8edf0439ccccf9ec82759afb2d7f7cad;hpb=205f5ba888cb2abb0b5411e105d1f770e6c2e0d1;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrclient.c b/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrclient.c index f633632..5ff9200 100644 --- a/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrclient.c +++ b/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrclient.c @@ -1,3 +1,23 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + #include #include #include @@ -5,318 +25,286 @@ #include "caedrinterface.h" #include "caedrutils.h" #include "caedrclient.h" -#include "caleserver.h" #include "logger.h" #include "oic_malloc.h" -#include "uthreadpool.h" /* for thread pool */ -#include "umutex.h" +#include "oic_string.h" +#include "cathreadpool.h" /* for thread pool */ +#include "camutex.h" +#include "uarraylist.h" #include "caadapterutils.h" -#include "com_iotivity_jar_CAEDRInterface.h" - -//#define DEBUG_MODE -#define TAG PCF("CA_EDR_CLIENT") - -static const char *METHODID_OBJECTNONPARAM = "()Landroid/bluetooth/BluetoothAdapter;"; -static const char *METHODID_STRINGNONPARAM = "()Ljava/lang/String;"; -static const char *CLASSPATH_BT_ADPATER = "android/bluetooth/BluetoothAdapter"; -static const char *CLASSPATH_BT_UUID = "java/util/UUID"; - -static const uint32_t STATE_CONNECTED = 1; -static const uint32_t STATE_DISCONNECTED = 0; - -static u_thread_pool_t gThreadPoolHandle = NULL; +#include "caremotehandler.h" + +#define TAG PCF("OIC_CA_EDR_CLIENT") + +static const char METHODID_CONTEXTNONPARAM[] = "()Landroid/content/Context;"; +static const char METHODID_OBJECTNONPARAM[] = "()Landroid/bluetooth/BluetoothAdapter;"; +static const char METHODID_OUTPUTNONPARAM[] = "()Ljava/io/OutputStream;"; +static const char METHODID_STRINGNONPARAM[] = "()Ljava/lang/String;"; +static const char METHODID_BT_DEVICEPARAM[] = + "(Ljava/lang/String;)Landroid/bluetooth/BluetoothDevice;"; +static const char CLASSPATH_BT_ADPATER[] = "android/bluetooth/BluetoothAdapter"; +static const char CLASSPATH_BT_DEVICE[] = "android/bluetooth/BluetoothDevice"; +static const char CLASSPATH_BT_INTERFACE[] = "org/iotivity/ca/CaEdrInterface"; +static const char CLASSPATH_BT_SOCKET[] = "android/bluetooth/BluetoothSocket"; +static const char CLASSPATH_BT_UUID[] = "java/util/UUID"; +static const char CLASSPATH_CONTEXT[] = "android/content/Context"; +static const char CLASSPATH_OUTPUT[] = "java/io/OutputStream"; static JavaVM *g_jvm; -static jobject gContext; - -// server socket instance -static jobject gServerSocketObject = NULL; +static jobject g_context; /** - * @var gMutexUnicastServer - * @brief Mutex to synchronize unicast server + * @var g_mutexStateList + * @brief Mutex to synchronize device state list */ -static u_mutex gMutexUnicastServer = NULL; +static ca_mutex g_mutexStateList = NULL; /** - * @var gStopUnicast - * @brief Flag to control the Receive Unicast Data Thread + * @var g_mutexObjectList + * @brief Mutex to synchronize device object list */ -static bool gStopUnicast = FALSE; +static ca_mutex g_mutexObjectList = NULL; /** - * @var gMutexMulticastServer - * @brief Mutex to synchronize secure multicast server + * @var g_edrErrorHandler + * @brief Error callback to update error in EDR */ -static u_mutex gMutexMulticastServer = NULL; - -/** - * @var gStopMulticast - * @brief Flag to control the Receive Multicast Data Thread - */ -static bool gStopMulticast = FALSE; - -/** - * @var gStopAccept - * @brief Flag to control the Accept Thread - */ -static bool gStopAccept = FALSE; - -typedef struct send_data { - char* address; - char* data; - uint32_t id; -} data_t; - -/** - @brief Thread context information for unicast, multicast and secured unicast server - */ -typedef struct -{ - bool *stopFlag; - CAAdapterServerType_t type; -} CAAdapterReceiveThreadContext_t; - -typedef struct -{ - bool *stopFlag; -} CAAdapterAcceptThreadContext_t; +static CAEDRErrorHandleCallback g_edrErrorHandler = NULL; /** * implement for BT-EDR adapter common method */ -CAResult_t CAEDRGetInterfaceInformation(CALocalConnectivity_t **info) +CAResult_t CAEDRGetInterfaceInformation(CAEndpoint_t **info) { - OIC_LOG_V(DEBUG, TAG, "IN - CAEDRGetInterfaceInformation"); - - CALocalConnectivity_t *netInfo = NULL; - - int32_t netInfoSize = 1; + OIC_LOG(DEBUG, TAG, "IN - CAEDRGetInterfaceInformation"); - netInfo = (CALocalConnectivity_t *) OICMalloc(sizeof(CALocalConnectivity_t) * netInfoSize); - if(NULL == netInfo) + if (!info) { - OIC_LOG_V(ERROR, TAG, "Invalid input.."); - return CA_MEMORY_ALLOC_FAILED; + OIC_LOG(ERROR, TAG, "endpoint info is null"); + return CA_STATUS_INVALID_PARAM; } - memset(netInfo, 0, sizeof(CALocalConnectivity_t) * netInfoSize); char *macAddress = NULL; CAResult_t ret = CAEDRGetInterfaceInfo(&macAddress); - OIC_LOG_V(ERROR, TAG, "address : %s", macAddress); - if (CA_STATUS_OK != ret || NULL == macAddress) + if (CA_STATUS_OK != ret) { OIC_LOG_V(ERROR, TAG, "Failed to get interface info [%d]", ret); - - OICFree(netInfo); OICFree(macAddress); return ret; } + if (!macAddress) + { + OIC_LOG(ERROR, TAG, "mac address is null"); + return CA_STATUS_FAILED; + } + OIC_LOG_V(DEBUG, TAG, "address : %s", macAddress); + // Create local endpoint using util function - CALocalConnectivity_t *endpoint = CAAdapterCreateLocalEndpoint(CA_EDR, macAddress); + CAEndpoint_t *endpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS, CA_ADAPTER_RFCOMM_BTEDR, + macAddress, 0); if (NULL == endpoint) { - OIC_LOG_V(ERROR, TAG, "Failed to create Local Endpoint!", - CA_MEMORY_ALLOC_FAILED); - OICFree(netInfo); + OIC_LOG(ERROR, TAG, "Failed to create Local Endpoint!"); OICFree(macAddress); - return CA_MEMORY_ALLOC_FAILED; + return CA_STATUS_FAILED; } // copy unicast server information - endpoint->isSecured = CA_FALSE; - memcpy(&netInfo[0], endpoint, sizeof(CALocalConnectivity_t)); + int32_t netInfoSize = 1; + CAEndpoint_t *netInfo = (CAEndpoint_t *)OICMalloc(sizeof(CAEndpoint_t) * netInfoSize); + if (NULL == netInfo) + { + OIC_LOG(ERROR, TAG, "Invalid input.."); + OICFree(macAddress); + CAFreeEndpoint(endpoint); + return CA_MEMORY_ALLOC_FAILED; + } + *netInfo = *endpoint; *info = netInfo; OICFree(macAddress); - CAAdapterFreeLocalEndpoint(endpoint); + CAFreeEndpoint(endpoint); - OIC_LOG_V(DEBUG, TAG, "OUT - CAEDRGetInterfaceInformation"); + OIC_LOG(DEBUG, TAG, "OUT - CAEDRGetInterfaceInformation"); return CA_STATUS_OK; } -void CAEDRTerminateClient() +void CAEDRClientTerminate() { OIC_LOG(DEBUG, TAG, "IN"); CAEDRTerminate(); OIC_LOG(DEBUG, TAG, "OUT"); } -CAResult_t CAEDRManagerReadData(void) +CAResult_t CAEDRManagerReadData() { - OIC_LOG_V(DEBUG, TAG, "IN"); - OIC_LOG_V(DEBUG, TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "IN"); + + OIC_LOG(DEBUG, TAG, "OUT"); return CA_NOT_SUPPORTED; } -CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const char *serviceUUID, - void *data, uint32_t dataLength, uint32_t *sentLength) +CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const uint8_t *data, + uint32_t dataLength) { - OIC_LOG_V(DEBUG, TAG, "IN"); - CAEDRSendUnicastMessage(remoteAddress, (const char*) data, dataLength); - OIC_LOG_V(DEBUG, TAG, "OUT"); - return CA_STATUS_OK; -} + VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null"); + VERIFY_NON_NULL(data, TAG, "data is null"); + CAResult_t result = CAEDRSendUnicastMessage(remoteAddress, data, dataLength); + return result; +} -CAResult_t CAEDRClientSendMulticastData(const char *serviceUUID, void *data, - uint32_t dataLength, uint32_t *sentLength) +CAResult_t CAEDRClientSendMulticastData(const uint8_t *data, uint32_t dataLength) { - OIC_LOG_V(DEBUG, TAG, "IN"); - CAEDRSendMulticastMessage((const char*) data, dataLength); - OIC_LOG_V(DEBUG, TAG, "OUT"); - return CA_STATUS_OK; + VERIFY_NON_NULL(data, TAG, "data is null"); + + CAResult_t result = CAEDRSendMulticastMessage(data, dataLength); + return result; } -void CAEDRClientUnsetCallbacks(void) +// It will be updated when android EDR support is added +void CAEDRClientUnsetCallbacks() { - OIC_LOG_V(DEBUG, TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); - OIC_LOG_V(DEBUG, TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "OUT"); } -void CAEDRClientDisconnectAll(void) +// It will be updated when android EDR support is added +void CAEDRClientDisconnectAll() { - OIC_LOG_V(DEBUG, TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); - OIC_LOG_V(DEBUG, TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "OUT"); } -CAResult_t CAEDRGetAdapterEnableState(CABool_t *state) +CAResult_t CAEDRGetAdapterEnableState(bool *state) { - OIC_LOG_V(DEBUG, TAG, "IN"); + VERIFY_NON_NULL(state, TAG, "state is null"); - jboolean isAttached = FALSE; - JNIEnv* env; - jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6); - if(res != JNI_OK) + if (!g_jvm) { - OIC_LOG_V(DEBUG, TAG, "CAEDRGetAdapterEnableState - Could not get JNIEnv pointer"); + OIC_LOG(ERROR, TAG, "g_jvm is null"); + return CA_STATUS_INVALID_PARAM; + } + 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(DEBUG, TAG, "CAEDRGetAdapterEnableState - Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); - if(res != JNI_OK) + if (JNI_OK != res) { - OIC_LOG_V(DEBUG, TAG, "AttachCurrentThread failed"); - return CA_STATUS_FAILED; + OIC_LOG(ERROR, TAG, "AttachCurrentThread failed"); + return CA_STATUS_INVALID_PARAM; } - isAttached = TRUE; + isAttached = true; } + + *state = false; jboolean ret = CAEDRNativeIsEnableBTAdapter(env); - if(ret) + if (ret) { - *state = CA_TRUE; - } - else - { - *state = CA_FALSE; + *state = true; } - if(isAttached) + if (isAttached) + { (*g_jvm)->DetachCurrentThread(g_jvm); + } - OIC_LOG_V(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } -//////////////////////////////////////////////////////////////////////////////////////////////////// -//FIXME getting context - -void CAEDRJniSetContext() +void CAEDRJniInitContext() { - OIC_LOG_V(DEBUG, TAG, "CAEDRJniSetContext"); + OIC_LOG(DEBUG, TAG, "CAEDRJniInitContext"); - gContext = CANativeJNIGetContext(); + g_context = (jobject) CANativeJNIGetContext(); } -void CAEDRCreateJNIInterfaceObject(jobject context) +CAResult_t CAEDRCreateJNIInterfaceObject(jobject context) { - JNIEnv* env; - OIC_LOG_V(DEBUG, TAG, "[EDRCore] CAEDRCreateJNIInterfaceObject"); + JNIEnv* env = NULL; + OIC_LOG(DEBUG, TAG, "CAEDRCreateJNIInterfaceObject"); if ((*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK) { - OIC_LOG_V(DEBUG, TAG, "[EDRCore] Could not get JNIEnv pointer"); - return; + OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer"); + return CA_STATUS_FAILED; } - //getApplicationContext - jclass contextClass = (*env)->FindClass(env, "android/content/Context"); - if (contextClass == 0) + + jmethodID mid_getApplicationContext = CAGetJNIMethodID(env, CLASSPATH_CONTEXT, + "getApplicationContext", + METHODID_CONTEXTNONPARAM); + if (!mid_getApplicationContext) { - OIC_LOG_V(DEBUG, TAG, "[EDRCore] Could not get context object class"); - return; + OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method"); + return CA_STATUS_FAILED; } - jmethodID getApplicationContextMethod = (*env)->GetMethodID(env, contextClass, - "getApplicationContext", "()Landroid/content/Context;"); - if (getApplicationContextMethod == 0) + jobject jApplicationContext = (*env)->CallObjectMethod(env, context, + mid_getApplicationContext); + if (!jApplicationContext) { - OIC_LOG_V(DEBUG, TAG, "[EDRCore] Could not get getApplicationContext method"); - return; + OIC_LOG(ERROR, TAG, "Could not get application context"); + return CA_STATUS_FAILED; } //Create EDRJniInterface instance - jclass EDRJniInterface = (*env)->FindClass(env, "com/iotivity/jar/CAEDRInterface"); + jclass EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE); if (!EDRJniInterface) { - OIC_LOG_V(DEBUG, TAG, "[EDRCore] Could not get CAEDRInterface class"); - return; + OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class"); + return CA_STATUS_FAILED; } - jmethodID EDRInterfaceConstructorMethod = (*env)->GetMethodID(env, - EDRJniInterface, "", "(Landroid/content/Context;)V"); + jmethodID EDRInterfaceConstructorMethod = (*env)->GetMethodID(env, EDRJniInterface, "", + "(Landroid/content/Context;)V"); if (!EDRInterfaceConstructorMethod) { - OIC_LOG_V(DEBUG, TAG, "[EDRCore] Could not get CAEDRInterface constructor method"); - return; + OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface constructor method"); + return CA_STATUS_FAILED; } - (*env)->NewObject(env, EDRJniInterface, EDRInterfaceConstructorMethod, context); - OIC_LOG_V(DEBUG, TAG, "[EDRCore] NewObject Success"); + (*env)->NewObject(env, EDRJniInterface, EDRInterfaceConstructorMethod, jApplicationContext); + OIC_LOG(DEBUG, TAG, "NewObject Success"); + return CA_STATUS_OK; } static void CAEDRDestroyMutex() { - OIC_LOG(DEBUG, TAG, "IN"); - - if (gMutexUnicastServer) + if (g_mutexStateList) { - u_mutex_free(gMutexUnicastServer); - gMutexUnicastServer = NULL; + ca_mutex_free(g_mutexStateList); + g_mutexStateList = NULL; } -#ifdef __WITH_DTLS__ - -#endif - - if (gMutexMulticastServer) + if (g_mutexObjectList) { - u_mutex_free(gMutexMulticastServer); - gMutexMulticastServer = NULL; + ca_mutex_free(g_mutexObjectList); + g_mutexObjectList = NULL; } - - OIC_LOG(DEBUG, TAG, "OUT"); } static CAResult_t CAEDRCreateMutex() { - OIC_LOG(DEBUG, TAG, "IN"); - - gMutexUnicastServer = u_mutex_new(); - if (!gMutexUnicastServer) + g_mutexStateList = ca_mutex_new(); + if (!g_mutexStateList) { OIC_LOG(ERROR, TAG, "Failed to created mutex!"); + + CAEDRDestroyMutex(); return CA_STATUS_FAILED; } -#ifdef __WITH_DTLS__ - -#endif - - gMutexMulticastServer = u_mutex_new(); - if (!gMutexMulticastServer) + g_mutexObjectList = ca_mutex_new(); + if (!g_mutexObjectList) { OIC_LOG(ERROR, TAG, "Failed to created mutex!"); @@ -324,84 +312,102 @@ static CAResult_t CAEDRCreateMutex() return CA_STATUS_FAILED; } - OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } -void CAEDRInitialize(u_thread_pool_t handle) +CAResult_t CAEDRInitialize() { OIC_LOG(DEBUG, TAG, "CAEDRInitialize"); - gThreadPoolHandle = handle; - CAEDRCoreJniInit(); - CAEDRJniSetContext(); + CAEDRJniInitContext(); // init mutex - CAEDRCreateMutex(); + CAResult_t result = CAEDRCreateMutex(); + if(CA_STATUS_OK != result) + { + OIC_LOG(ERROR, TAG, "CAEDRInitialize - Could not create mutex"); + return result; + } - jboolean isAttached = FALSE; - JNIEnv* env; - jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6); - if(res != JNI_OK) + 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_V(DEBUG, TAG, "CAEDRInitialize - Could not get JNIEnv pointer"); + OIC_LOG(DEBUG, TAG, "CAEDRInitialize - Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); - if(res != JNI_OK) + if (JNI_OK != res) { - OIC_LOG_V(DEBUG, TAG, "AttachCurrentThread failed"); - return; + OIC_LOG(ERROR, TAG, "AttachCurrentThread failed"); + return CA_STATUS_NOT_INITIALIZED; } - isAttached = TRUE; + isAttached = true; } - jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env); - if(jni_address) + if (jni_address) { const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL); - OIC_LOG_V(DEBUG, TAG, "My BT Address is %s ", localAddress); + OIC_LOG_V(DEBUG, TAG, "My BT Address is %s", localAddress); + (*env)->ReleaseStringUTFChars(env, jni_address, localAddress); } + (*env)->DeleteLocalRef(env, jni_address); + ca_mutex_lock(g_mutexStateList); CAEDRNativeCreateDeviceStateList(); + ca_mutex_unlock(g_mutexStateList); + + ca_mutex_lock(g_mutexObjectList); CAEDRNativeCreateDeviceSocketList(); + ca_mutex_unlock(g_mutexObjectList); - if(isAttached) + if (isAttached) + { (*g_jvm)->DetachCurrentThread(g_jvm); + } - if(gContext) + if (g_context) { - //FIXME - CAEDRCreateJNIInterfaceObject(gContext); /* create java CAEDRInterface instance*/ + CAEDRCreateJNIInterfaceObject(g_context); /* create java CaEdrInterface instance*/ } OIC_LOG(DEBUG, TAG, "OUT"); + + return result; } void CAEDRTerminate() { OIC_LOG(DEBUG, TAG, "CAEDRTerminate"); - jboolean isAttached = FALSE; - JNIEnv* env; - jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6); - if(res != JNI_OK) + 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_V(DEBUG, TAG, "CAEDRTerminate - Could not get JNIEnv pointer"); + OIC_LOG(DEBUG, TAG, "CAEDRTerminate - Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); - if(res != JNI_OK) + if (JNI_OK != res) { - OIC_LOG_V(DEBUG, TAG, "AttachCurrentThread failed"); + OIC_LOG(ERROR, TAG, "AttachCurrentThread failed"); return; } - isAttached = TRUE; + isAttached = true; + } + + if (isAttached) + { + (*g_jvm)->DetachCurrentThread(g_jvm); } - gStopAccept = TRUE; - gStopMulticast = TRUE; - gStopUnicast = TRUE; + if (g_context) + { + (*env)->DeleteGlobalRef(env, g_context); + g_context = NULL; + } CAEDRNativeSocketCloseToAll(env); @@ -410,57 +416,130 @@ void CAEDRTerminate() CAEDRNativeRemoveAllDeviceState(); CAEDRNativeRemoveAllDeviceSocket(env); + CAEDRDestroyJniInterface(); +} + +CAResult_t CAEDRDestroyJniInterface() +{ + OIC_LOG(DEBUG, TAG, "CAEDRDestroyJniInterface"); + + 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; + } + + jclass jni_EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE); + if (!jni_EDRJniInterface) + { + OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class"); + goto error_exit; + } - if(isAttached) + jmethodID jni_EDRInterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_EDRJniInterface, + "destroyEdrInterface", + "()V"); + if (!jni_EDRInterfaceDestroyMethod) + { + OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface destroy method"); + goto error_exit; + } + + (*env)->CallStaticVoidMethod(env, jni_EDRJniInterface, jni_EDRInterfaceDestroyMethod); + + if ((*env)->ExceptionCheck(env)) + { + OIC_LOG(ERROR, TAG, "destroyEdrInterface has failed"); + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + goto error_exit; + } + + OIC_LOG(DEBUG, TAG, "Destroy instance for CaEdrInterface"); + + if (isAttached) + { (*g_jvm)->DetachCurrentThread(g_jvm); + } + + return CA_STATUS_OK; + +error_exit: + + if (isAttached) + { + (*g_jvm)->DetachCurrentThread(g_jvm); + } + + return CA_STATUS_FAILED; } void CAEDRCoreJniInit() { - OIC_LOG_V(DEBUG, TAG, "CAEdrClientJniInit"); - g_jvm = CANativeJNIGetJavaVM(); + OIC_LOG(DEBUG, TAG, "CAEdrClientJniInit"); + g_jvm = (JavaVM*) CANativeJNIGetJavaVM(); } -int32_t CAEDRSendUnicastMessage(const char* address, const char* data, uint32_t dataLen) +CAResult_t CAEDRSendUnicastMessage(const char* address, const uint8_t* data, uint32_t dataLen) { - OIC_LOG_V(DEBUG, TAG, "CAEDRSendUnicastMessage(%s, %s)", address, data); + VERIFY_NON_NULL(address, TAG, "address is null"); + VERIFY_NON_NULL(data, TAG, "data is null"); - CAEDRSendUnicastMessageImpl(address, data, dataLen); - return 0; + CAResult_t result = CAEDRSendUnicastMessageImpl(address, data, dataLen); + return result; } -int32_t CAEDRSendMulticastMessage(const char* data, uint32_t dataLen) +CAResult_t CAEDRSendMulticastMessage(const uint8_t* data, uint32_t dataLen) { - OIC_LOG_V(DEBUG, TAG, "CAEDRSendMulticastMessage(%s)", data); + VERIFY_NON_NULL(data, TAG, "data is null"); - jboolean isAttached = FALSE; - JNIEnv* env; - jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6); - if(res != JNI_OK) + 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_V(DEBUG, TAG, "CAEDRSendMulticastMessage - Could not get JNIEnv pointer"); + OIC_LOG(DEBUG, TAG, "CAEDRSendMulticastMessage - Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); - if(res != JNI_OK) + if (JNI_OK != res) { - OIC_LOG_V(DEBUG, TAG, "AttachCurrentThread failed"); - return 0; + OIC_LOG(ERROR, TAG, "AttachCurrentThread failed"); + return CA_STATUS_INVALID_PARAM; } - isAttached = TRUE; + isAttached = true; } - CAEDRSendMulticastMessageImpl(env, data, dataLen); - - OIC_LOG_V(DEBUG, TAG, "sent data"); + CAResult_t result = CAEDRSendMulticastMessageImpl(env, data, dataLen); + if(CA_STATUS_OK != result) + { + OIC_LOG(ERROR, TAG, "CAEDRSendMulticastMessage - could not send multicast message"); + return result; + } - if(isAttached) + if (isAttached) { - OIC_LOG_V(DEBUG, TAG, "DetachCurrentThread"); -// (*g_jvm)->DetachCurrentThread(g_jvm); + OIC_LOG(DEBUG, TAG, "DetachCurrentThread"); + (*g_jvm)->DetachCurrentThread(g_jvm); } - OIC_LOG_V(DEBUG, TAG, "OUT - CAEDRSendMulticastMessage"); - return 1; + OIC_LOG(DEBUG, TAG, "OUT - CAEDRSendMulticastMessage"); + return CA_STATUS_OK; } CAResult_t CAEDRGetInterfaceInfo(char **address) @@ -469,420 +548,547 @@ CAResult_t CAEDRGetInterfaceInfo(char **address) return CA_STATUS_OK; } -void CAEDRGetLocalAddress(char** address) +void CAEDRGetLocalAddress(char **address) { - jboolean isAttached = FALSE; - JNIEnv* env; - jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6); - if(res != JNI_OK) + 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_V(DEBUG, TAG, "CAEDRGetLocalAddress - Could not get JNIEnv pointer"); + OIC_LOG(DEBUG, TAG, "CAEDRGetLocalAddress - Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); - if(res != JNI_OK) + if (JNI_OK != res) { - OIC_LOG_V(DEBUG, TAG, "AttachCurrentThread failed"); + OIC_LOG(ERROR, TAG, "AttachCurrentThread failed"); return; } - isAttached = TRUE; + isAttached = true; } jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env); - if(jni_address) + if (jni_address) { const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL); - *address = (char*)OICMalloc(strlen(localAddress) + 1); + *address = OICStrdup(localAddress); if (*address == NULL) { + if (isAttached) + { + (*g_jvm)->DetachCurrentThread(g_jvm); + } + (*env)->ReleaseStringUTFChars(env, jni_address, localAddress); + (*env)->DeleteLocalRef(env, jni_address); return; } - memcpy(*address, localAddress, strlen(localAddress)); + + (*env)->ReleaseStringUTFChars(env, jni_address, localAddress); + (*env)->DeleteLocalRef(env, jni_address); } OIC_LOG_V(DEBUG, TAG, "Local Address : %s", *address); - if(isAttached) + if (isAttached) + { (*g_jvm)->DetachCurrentThread(g_jvm); + } } -int32_t CAEDRSendUnicastMessageImpl(const char* address, const char* data, uint32_t dataLen) +CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const uint8_t* data, uint32_t dataLen) { - OIC_LOG_V(DEBUG, TAG, "CAEDRSendUnicastMessageImpl, address: %s, data: %s", address, data); + VERIFY_NON_NULL(address, TAG, "address is null"); + VERIFY_NON_NULL(data, TAG, "data is null"); - jboolean isAttached = FALSE; - JNIEnv* env; - jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6); - if(res != JNI_OK) + 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_V(DEBUG, TAG, "CAEDRSendUnicastMessageImpl - Could not get JNIEnv pointer"); + OIC_LOG(DEBUG, TAG, "CAEDRSendUnicastMessageImpl - Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); - if(res != JNI_OK) + if (JNI_OK != res) { - OIC_LOG_V(DEBUG, TAG, "AttachCurrentThread failed"); - return 0; + OIC_LOG(ERROR, TAG, "AttachCurrentThread failed"); + return CA_STATUS_INVALID_PARAM; } - isAttached = TRUE; + isAttached = true; } - OIC_LOG(DEBUG, TAG, "[EDR][Native] set byteArray for data"); + OIC_LOG(DEBUG, TAG, "set byteArray for data"); // get bonded device list jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env); - if(!jni_arrayPairedDevices) + if (!jni_arrayPairedDevices) { - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] jni_arrayPairedDevices is empty"); - return 0; + OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty"); + if (isAttached) + { + (*g_jvm)->DetachCurrentThread(g_jvm); + } + return CA_STATUS_INVALID_PARAM; } // Get information from array of devices + jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE); + jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName", + METHODID_STRINGNONPARAM); + jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress", + METHODID_STRINGNONPARAM); + jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices); - jsize i; - for( i = 0 ; i < length ; i++ ) + for (jsize i = 0; i < length; i++) { - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] start to check device"); + OIC_LOG(DEBUG, TAG, "start to check device"); // get name, address from BT device jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i); - - jclass jni_cid_BTDevice = (*env)->FindClass(env, "android/bluetooth/BluetoothDevice"); - jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName", "()Ljava/lang/String;"); - jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress", "()Ljava/lang/String;"); - jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName); - if(j_str_name) + if (j_str_name) { const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL); - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] getBondedDevices: ~~device name is %s", name); + OIC_LOG_V(DEBUG, TAG, "device name is %s", name); (*env)->ReleaseStringUTFChars(env, j_str_name, name); + (*env)->DeleteLocalRef(env, j_str_name); } jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress); const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL); - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] getBondedDevices: ~~device address is %s", remoteAddress); + (*env)->DeleteLocalRef(env, j_obj_device); + if (!remoteAddress) + { + OIC_LOG(ERROR, TAG, "remoteAddress is null"); + if (isAttached) + { + (*g_jvm)->DetachCurrentThread(g_jvm); + } + + (*env)->DeleteLocalRef(env, j_str_address); + (*env)->DeleteLocalRef(env, jni_arrayPairedDevices); + (*env)->DeleteLocalRef(env, jni_cid_BTDevice); + return CA_STATUS_INVALID_PARAM; + } + OIC_LOG_V(DEBUG, TAG, "device address is %s", remoteAddress); // find address - if(!strcmp(remoteAddress, address)) + if (!strcmp(remoteAddress, address)) { - CAEDRNativeSendData(env, remoteAddress, data, dataLen, i); + CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen); + (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress); + (*env)->DeleteLocalRef(env, j_str_address); + if (CA_STATUS_OK != res) + { + (*env)->DeleteLocalRef(env, jni_arrayPairedDevices); + (*env)->DeleteLocalRef(env, jni_cid_BTDevice); + return res; + } + break; } + (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress); + (*env)->DeleteLocalRef(env, j_str_address); } - if(isAttached) + (*env)->DeleteLocalRef(env, jni_arrayPairedDevices); + (*env)->DeleteLocalRef(env, jni_cid_BTDevice); + + if (isAttached) + { (*g_jvm)->DetachCurrentThread(g_jvm); + } - return 1; + return CA_STATUS_OK; } -int32_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const char* data, uint32_t dataLen) +CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, uint32_t dataLen) { - OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %s, %d", data, dataLen); + VERIFY_NON_NULL(env, TAG, "env is null"); + VERIFY_NON_NULL(data, TAG, "data is null"); // get bonded device list jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env); - if(!jni_arrayPairedDevices) + if (!jni_arrayPairedDevices) { - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] jni_arrayPairedDevices is empty"); - return 0; + OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty"); + return CA_STATUS_INVALID_PARAM; } // Get information from array of devices + jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE); + jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName", + METHODID_STRINGNONPARAM); + jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress", + METHODID_STRINGNONPARAM); + jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices); - jsize i; - for( i = 0 ; i < length ; i++ ) + for (jsize i = 0; i < length; i++) { // get name, address from BT device jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i); - - jclass jni_cid_BTDevice = (*env)->FindClass(env, "android/bluetooth/BluetoothDevice"); - jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName", "()Ljava/lang/String;"); - jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress", "()Ljava/lang/String;"); - jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName); + jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress); - if(j_str_name) + if (j_str_name && j_str_address) { const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL); - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] getBondedDevices: ~~device name is %s", name); + const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL); + if (name && remoteAddress) + { + OIC_LOG_V(DEBUG, TAG, "device name is %s, address is %s", name, remoteAddress); + + CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen); + if (CA_STATUS_OK != res) + { + OIC_LOG_V(ERROR, TAG, "Failed to send multicast message to : %s", + remoteAddress); + g_edrErrorHandler(remoteAddress, data, dataLen, res); + } + } (*env)->ReleaseStringUTFChars(env, j_str_name, name); + (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress); } - jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress); - const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL); - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] getBondedDevices: ~~device address is %s", remoteAddress); - - // find address - CAEDRNativeSendData(env, remoteAddress, data, dataLen, i); + (*env)->DeleteLocalRef(env, j_obj_device); + (*env)->DeleteLocalRef(env, j_str_name); + (*env)->DeleteLocalRef(env, j_str_address); } - return 1; + (*env)->DeleteLocalRef(env, jni_arrayPairedDevices); + (*env)->DeleteLocalRef(env, jni_cid_BTDevice); + + return CA_STATUS_OK; } -/** - * EDR Method - */ -void CAEDRNativeSendData(JNIEnv *env, const char* address, const char* data, uint32_t dataLength, uint32_t id) +CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const uint8_t *data, + uint32_t dataLength) { - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btSendData logic start : %s, %d", data, dataLength); + VERIFY_NON_NULL(env, TAG, "env is null"); + VERIFY_NON_NULL(address, TAG, "address is null"); + VERIFY_NON_NULL(data, TAG, "data is null"); - if(!CAEDRNativeIsEnableBTAdapter(env)) + if (!CAEDRNativeIsEnableBTAdapter(env)) { - OIC_LOG(DEBUG, TAG, "BT adpater is not enable"); - return; + OIC_LOG(INFO, TAG, "BT adapter is not enabled"); + return CA_ADAPTER_NOT_ENABLED; } - if(STATE_DISCONNECTED == CAEDRIsConnectedDevice(address)) + if (STATE_DISCONNECTED == CAEDRIsConnectedDevice(address)) { // connect before send data - OIC_LOG(DEBUG, TAG, "[EDR][Native] connect before send data"); + OIC_LOG_V(DEBUG, TAG, "try to connect with [%s] before sending data", address); - if(NULL == address) - { - OIC_LOG(DEBUG, TAG, "[EDR][Native] remote address is empty"); - return; - } - else + CAResult_t res = CAEDRNativeConnect(env, address); + if (CA_STATUS_OK != res) { - CAEDRNativeConnect(env, address, id); + return res; } } - if(STATE_CONNECTED == CAEDRIsConnectedDevice(address)) + if (STATE_CONNECTED == CAEDRIsConnectedDevice(address)) { - if(!((*env)->ExceptionCheck(env))) + if (!((*env)->ExceptionCheck(env))) { - jclass jni_cid_BTsocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket"); - if(!jni_cid_BTsocket) + jclass jni_cid_BTsocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET); + if (!jni_cid_BTsocket) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: jni_cid_BTsocket is null"); - return; + OIC_LOG(ERROR, TAG, "jni_cid_BTsocket is null"); + return CA_STATUS_FAILED; } - jmethodID jni_mid_getOutputStream = (*env)->GetMethodID(env, jni_cid_BTsocket, "getOutputStream", "()Ljava/io/OutputStream;"); - if(!jni_mid_getOutputStream) + jmethodID jni_mid_getOutputStream = (*env)->GetMethodID(env, jni_cid_BTsocket, + "getOutputStream", + METHODID_OUTPUTNONPARAM); + if (!jni_mid_getOutputStream) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: jni_mid_getOutputStream is null"); - return; + OIC_LOG(ERROR, TAG, "jni_mid_getOutputStream is null"); + (*env)->DeleteLocalRef(env, jni_cid_BTsocket); + return CA_STATUS_FAILED; } - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btSendData: Get MethodID for i/o stream..%d", id); - jobject jni_obj_socket = CAEDRNativeGetDeviceSocket(id); - if(!jni_obj_socket) + OIC_LOG(DEBUG, TAG, "Get MethodID for i/o stream"); + + jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address); + if (!jni_obj_socket) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: jni_socket is not available"); - return; + OIC_LOG(ERROR, TAG, "jni_socket is not available"); + (*env)->DeleteLocalRef(env, jni_cid_BTsocket); + return CA_STATUS_FAILED; } - jobject jni_obj_outputStream = (*env)->CallObjectMethod(env, jni_obj_socket, jni_mid_getOutputStream); - if(!jni_obj_outputStream) + jobject jni_obj_outputStream = (*env)->CallObjectMethod(env, jni_obj_socket, + jni_mid_getOutputStream); + if (!jni_obj_outputStream) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: jni_obj_outputStream is null"); - return; + OIC_LOG(ERROR, TAG, "jni_obj_outputStream is null"); + (*env)->DeleteLocalRef(env, jni_cid_BTsocket); + return CA_STATUS_FAILED; } - OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: ready outputStream.."); + OIC_LOG(DEBUG, TAG, "ready outputStream.."); - jclass jni_cid_OutputStream = (*env)->FindClass(env, "java/io/OutputStream"); - if(!jni_cid_OutputStream) + jclass jni_cid_OutputStream = (*env)->FindClass(env, CLASSPATH_OUTPUT); + if (!jni_cid_OutputStream) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: jni_cid_OutputStream is null"); - return; + OIC_LOG(ERROR, TAG, "jni_cid_OutputStream is null"); + (*env)->DeleteLocalRef(env, jni_cid_BTsocket); + (*env)->DeleteLocalRef(env, jni_obj_outputStream); + return CA_STATUS_FAILED; } - jmethodID jni_mid_write = (*env)->GetMethodID(env, jni_cid_OutputStream, "write", "([BII)V"); - if(!jni_mid_write) + jmethodID jni_mid_write = (*env)->GetMethodID(env, jni_cid_OutputStream, "write", + "([BII)V"); + if (!jni_mid_write) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: jni_mid_write is null"); - return; + OIC_LOG(ERROR, TAG, "jni_mid_write is null"); + (*env)->DeleteLocalRef(env, jni_cid_BTsocket); + (*env)->DeleteLocalRef(env, jni_obj_outputStream); + (*env)->DeleteLocalRef(env, jni_cid_OutputStream); + return CA_STATUS_FAILED; } - jbyteArray jbuf; - jbuf = (*env)->NewByteArray(env, dataLength); - (*env)->SetByteArrayRegion(env, jbuf, 0, dataLength, (jbyte*)data); + jbyteArray jbuf = (*env)->NewByteArray(env, dataLength); + (*env)->SetByteArrayRegion(env, jbuf, 0, dataLength, (jbyte*) data); - (*env)->CallVoidMethod(env, jni_obj_outputStream, jni_mid_write, jbuf, (jint)0, (jint)dataLength); + (*env)->CallVoidMethod(env, jni_obj_outputStream, jni_mid_write, jbuf, (jint) 0, + (jint) dataLength); - if((*env)->ExceptionCheck(env)) + (*env)->DeleteLocalRef(env, jni_cid_BTsocket); + (*env)->DeleteLocalRef(env, jni_obj_outputStream); + (*env)->DeleteLocalRef(env, jni_cid_OutputStream); + (*env)->DeleteLocalRef(env, jbuf); + + if ((*env)->ExceptionCheck(env)) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: Write Error!!!"); + OIC_LOG(ERROR, TAG, "Failed to write data in outputStram"); (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); - return; + return CA_STATUS_FAILED; } - OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: Write Success"); + OIC_LOG_V(INFO, TAG, "EDR sendTo is successful: %u bytes, to %s", + dataLength, address); } else { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); - OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: error!!"); - return; + OIC_LOG(ERROR, TAG, "error!!"); + return CA_STATUS_FAILED; } } else { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: BT connection is not completed!!"); + OIC_LOG(DEBUG, TAG, "BT connection is not completed!!"); } + + return CA_STATUS_OK; } -void CAEDRNativeConnect(JNIEnv *env, const char* address, uint32_t id) +CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect.."); + VERIFY_NON_NULL(address, TAG, "address is null"); - if(!CAEDRNativeIsEnableBTAdapter(env)) + if (!CAEDRNativeIsEnableBTAdapter(env)) { - OIC_LOG(DEBUG, TAG, "BT adpater is not enable"); - return; + OIC_LOG(INFO, TAG, "BT adapter is not enabled"); + return CA_ADAPTER_NOT_ENABLED; } jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER); - if(!jni_cid_BTAdapter) + if (!jni_cid_BTAdapter) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: jni_cid_BTAdapter is null"); - return; + OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null"); + return CA_STATUS_FAILED; } // get BTadpater - jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter, "getDefaultAdapter", METHODID_OBJECTNONPARAM); - if(!jni_mid_getDefaultAdapter) + jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter, + "getDefaultAdapter", + METHODID_OBJECTNONPARAM); + if (!jni_mid_getDefaultAdapter) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: jni_mid_getDefaultAdapter is null"); - return; + OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null"); + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + return CA_STATUS_FAILED; } - jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter, jni_mid_getDefaultAdapter); - if(!jni_obj_BTAdapter) + jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter, + jni_mid_getDefaultAdapter); + if (!jni_obj_BTAdapter) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: jni_obj_BTAdapter is null"); - return; + OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null"); + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + return CA_STATUS_FAILED; } // get remote bluetooth device - jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter, "getRemoteDevice", - "(Ljava/lang/String;)Landroid/bluetooth/BluetoothDevice;"); - if(!jni_mid_getRemoteDevice) + jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter, + "getRemoteDevice", + METHODID_BT_DEVICEPARAM); + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + if (!jni_mid_getRemoteDevice) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: jni_mid_getRemoteDevice is null"); - return; + OIC_LOG(ERROR, TAG, "jni_mid_getRemoteDevice is null"); + (*env)->DeleteLocalRef(env, jni_obj_BTAdapter); + return CA_STATUS_FAILED; } - //jstring jni_address = (*env)->NewStringUTF(env, "B8:5E:7B:54:52:1C"); jstring jni_address = (*env)->NewStringUTF(env, address); - jobject jni_obj_remoteBTDevice = (*env)->CallObjectMethod(env, jni_obj_BTAdapter, jni_mid_getRemoteDevice, jni_address); - if(!jni_obj_remoteBTDevice) + jobject jni_obj_remoteBTDevice = (*env)->CallObjectMethod(env, jni_obj_BTAdapter, + jni_mid_getRemoteDevice, jni_address); + (*env)->DeleteLocalRef(env, jni_address); + (*env)->DeleteLocalRef(env, jni_obj_BTAdapter); + if (!jni_obj_remoteBTDevice) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: jni_obj_remoteBTDevice is null"); - return; + OIC_LOG(ERROR, TAG, "jni_obj_remoteBTDevice is null"); + return CA_STATUS_FAILED; } // get create Rfcomm Socket method ID - jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, "android/bluetooth/BluetoothDevice"); - if(!jni_cid_BluetoothDevice) + jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE); + if (!jni_cid_BluetoothDevice) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: jni_cid_BluetoothDevice is null"); - return; + OIC_LOG(ERROR, TAG, "jni_cid_BluetoothDevice is null"); + (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice); + return CA_STATUS_FAILED; } - jmethodID jni_mid_createSocket = (*env)->GetMethodID(env, jni_cid_BluetoothDevice, - "createInsecureRfcommSocketToServiceRecord","(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;"); - if(!jni_mid_createSocket) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: jni_mid_createSocket is null"); - return; + jmethodID jni_mid_createSocket = (*env)->GetMethodID( + env, jni_cid_BluetoothDevice, "createInsecureRfcommSocketToServiceRecord", + "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;"); + (*env)->DeleteLocalRef(env, jni_cid_BluetoothDevice); + if (!jni_mid_createSocket) + { + OIC_LOG(ERROR, TAG, "jni_mid_createSocket is null"); + (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice); + return CA_STATUS_FAILED; } - // createInsecureRfcommSocketToServiceRecord / createRfcommSocketToServiceRecord // setting UUID jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID); - if(!jni_cid_uuid) + if (!jni_cid_uuid) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: jni_cid_uuid is null"); - return; + OIC_LOG(ERROR, TAG, "jni_cid_uuid is null"); + (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice); + return CA_STATUS_FAILED; } - jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_uuid, "fromString", - "(Ljava/lang/String;)Ljava/util/UUID;"); - if(!jni_mid_fromString) + jmethodID jni_mid_fromString = (*env)->GetStaticMethodID( + env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;"); + if (!jni_mid_fromString) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: jni_mid_fromString is null"); - return; + OIC_LOG(ERROR, TAG, "jni_mid_fromString is null"); + (*env)->DeleteLocalRef(env, jni_cid_uuid); + (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice); + return CA_STATUS_FAILED; } - jstring jni_uuid = (*env)->NewStringUTF(env, "00000000-0000-0000-0000-0000cdab0000"); - jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString, jni_uuid); - if(!jni_obj_uuid) + jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID); + if (!jni_uuid) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: jni_obj_uuid is null"); - return; + OIC_LOG(ERROR, TAG, "jni_uuid is null"); + (*env)->DeleteLocalRef(env, jni_cid_uuid); + (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice); + return CA_STATUS_FAILED; + } + jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString, + jni_uuid); + (*env)->DeleteLocalRef(env, jni_cid_uuid); + (*env)->DeleteLocalRef(env, jni_uuid); + if (!jni_obj_uuid) + { + OIC_LOG(ERROR, TAG, "jni_obj_uuid is null"); + (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice); + return CA_STATUS_FAILED; } // create socket - jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice, jni_mid_createSocket, jni_obj_uuid); - if(!jni_obj_BTSocket) + jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice, + jni_mid_createSocket, jni_obj_uuid); + (*env)->DeleteLocalRef(env, jni_obj_uuid); + (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice); + if (!jni_obj_BTSocket) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: jni_obj_BTSocket is null"); - return; + OIC_LOG(ERROR, TAG, "jni_obj_BTSocket is null"); + return CA_STATUS_FAILED; } // connect - jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket"); - if(!jni_cid_BTSocket) + jclass jni_cid_BTSocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET); + if (!jni_cid_BTSocket) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: jni_cid_BTSocket is null"); - return; + OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null"); + (*env)->DeleteLocalRef(env, jni_obj_BTSocket); + return CA_STATUS_FAILED; } jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_BTSocket, "connect", "()V"); - if(!jni_mid_connect) + (*env)->DeleteLocalRef(env, jni_cid_BTSocket); + if (!jni_mid_connect) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: jni_mid_connect is null"); - return; + OIC_LOG(ERROR, TAG, "jni_mid_connect is null"); + (*env)->DeleteLocalRef(env, jni_obj_BTSocket); + return CA_STATUS_FAILED; } - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: initiating connection..."); + OIC_LOG(DEBUG, TAG, "initiating connection..."); (*env)->CallVoidMethod(env, jni_obj_BTSocket, jni_mid_connect); - if((*env)->ExceptionCheck(env)) + if ((*env)->ExceptionCheck(env)) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: Connect is Failed!!!"); + OIC_LOG(ERROR, TAG, "Connect is Failed!!!"); (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); - return; + return CA_STATUS_FAILED; } // set socket to list jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket); + if (!jni_socket) + { + OIC_LOG(ERROR, TAG, "jni_socket is null"); + (*env)->DeleteLocalRef(env, jni_obj_BTSocket); + return CA_STATUS_FAILED; + } + ca_mutex_lock(g_mutexObjectList); CAEDRNativeAddDeviceSocketToList(env, jni_socket); + (*env)->DeleteGlobalRef(env, jni_socket); + (*env)->DeleteLocalRef(env, jni_obj_BTSocket); + ca_mutex_unlock(g_mutexObjectList); // update state + ca_mutex_lock(g_mutexStateList); CAEDRUpdateDeviceState(STATE_CONNECTED, address); + ca_mutex_unlock(g_mutexStateList); - OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: connected"); + OIC_LOG(DEBUG, TAG, "successfully connected"); + + return CA_STATUS_OK; } -void CAEDRNativeSocketClose(JNIEnv *env, const char* address, uint32_t id) +void CAEDRNativeSocketClose(JNIEnv *env, const char *address) { + VERIFY_NON_NULL_VOID(address, TAG, "address is null"); jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket"); - if(!jni_cid_BTSocket) + if (!jni_cid_BTSocket) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] close: jni_cid_BTSocket is null"); + OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null"); return; } jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_BTSocket, "close", "()V"); - if(!jni_mid_close) + if (!jni_mid_close) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] close: jni_mid_close is null"); + OIC_LOG(ERROR, TAG, "jni_mid_close is null"); return; } - jobject jni_obj_socket = CAEDRNativeGetDeviceSocket(id); - if(!jni_obj_socket) + jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address); + if (!jni_obj_socket) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] close: jni_obj_socket is not available"); + OIC_LOG(ERROR, TAG, "jni_obj_socket is not available"); return; } (*env)->CallVoidMethod(env, jni_obj_socket, jni_mid_close); - if((*env)->ExceptionCheck(env)) + if ((*env)->ExceptionCheck(env)) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] close: close is Failed!!!"); + OIC_LOG(ERROR, TAG, "close is Failed!!!"); (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); return; @@ -892,14 +1098,20 @@ void CAEDRNativeSocketClose(JNIEnv *env, const char* address, uint32_t id) CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket); // update state + ca_mutex_lock(g_mutexStateList); CAEDRUpdateDeviceState(STATE_DISCONNECTED, address); + ca_mutex_unlock(g_mutexStateList); - OIC_LOG(DEBUG, TAG, "[EDR][Native] close: disconnected"); + OIC_LOG_V(DEBUG, TAG, "disconnected with [%s]", address); } -void CAEDRInitializeClient(u_thread_pool_t handle) +CAResult_t CAEDRClientInitialize() { - OIC_LOG(DEBUG, TAG, "IN"); - CAEDRInitialize(handle); - OIC_LOG(DEBUG, TAG, "OUT"); + CAResult_t result = CAEDRInitialize(); + return result; +} + +void CAEDRSetErrorHandler(CAEDRErrorHandleCallback errorHandleCallback) +{ + g_edrErrorHandler = errorHandleCallback; }