added to call unregisterReceiver for Android BT/BLE.
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_edr_adapter / android / caedrclient.c
index 3d944ee..99c4523 100644 (file)
@@ -32,6 +32,7 @@
 #include "camutex.h"
 #include "uarraylist.h"
 #include "caadapterutils.h"
+#include "caremotehandler.h"
 
 //#define DEBUG_MODE
 #define TAG PCF("CA_EDR_CLIENT")
@@ -97,6 +98,12 @@ static ca_mutex g_mutexStateList = NULL;
  */
 static ca_mutex g_mutexObjectList = NULL;
 
+/**
+ * @var g_edrErrorHandler
+ * @brief Error callback to update error in EDR
+ */
+static CAEDRErrorHandleCallback g_edrErrorHandler = NULL;
+
 typedef struct send_data
 {
     char* address;
@@ -128,31 +135,28 @@ CAResult_t CAEDRGetInterfaceInformation(CAEndpoint_t **info)
     if (!info)
     {
         OIC_LOG(ERROR, TAG, "endpoint info is null");
-        return CA_STATUS_FAILED;
+        return CA_STATUS_INVALID_PARAM;
     }
 
-    int32_t netInfoSize = 1;
-
     char *macAddress = NULL;
     CAResult_t ret = CAEDRGetInterfaceInfo(&macAddress);
-    OIC_LOG_V(ERROR, TAG, "address : %s", macAddress);
-    if (NULL == macAddress)
-    {
-        OIC_LOG(ERROR, TAG, "mac address is null");
-
-        return CA_STATUS_FAILED;
-    }
     if (CA_STATUS_OK != ret)
     {
         OIC_LOG_V(ERROR, TAG, "Failed to get interface info [%d]", ret);
-
         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
-    CAEndpoint_t *endpoint = CAAdapterCreateEndpoint(CA_DEFAULT_FLAGS,
-                                                     CA_ADAPTER_RFCOMM_BTEDR, macAddress, 0);
+    CAEndpoint_t *endpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS, CA_ADAPTER_RFCOMM_BTEDR,
+                                                    macAddress, 0);
     if (NULL == endpoint)
     {
         OIC_LOG(ERROR, TAG, "Failed to create Local Endpoint!");
@@ -161,19 +165,20 @@ CAResult_t CAEDRGetInterfaceInformation(CAEndpoint_t **info)
     }
 
     // copy unicast server information
+    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);
-        CAAdapterFreeEndpoint(endpoint);
+        CAFreeEndpoint(endpoint);
         return CA_MEMORY_ALLOC_FAILED;
     }
     *netInfo = *endpoint;
     *info = netInfo;
 
     OICFree(macAddress);
-    CAAdapterFreeEndpoint(endpoint);
+    CAFreeEndpoint(endpoint);
 
     OIC_LOG(DEBUG, TAG, "OUT - CAEDRGetInterfaceInformation");
     return CA_STATUS_OK;
@@ -186,7 +191,7 @@ void CAEDRClientTerminate()
     OIC_LOG(DEBUG, TAG, "OUT");
 }
 
-CAResult_t CAEDRManagerReadData(void)
+CAResult_t CAEDRManagerReadData()
 {
     OIC_LOG(DEBUG, TAG, "IN");
 
@@ -194,26 +199,30 @@ CAResult_t CAEDRManagerReadData(void)
     return CA_NOT_SUPPORTED;
 }
 
-CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const char *serviceUUID,
-                                      const void *data, uint32_t dataLength, uint32_t *sentLength)
+CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const uint8_t *data,
+                                      uint32_t dataLength)
 {
+    VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
+    VERIFY_NON_NULL(data, TAG, "data is null");
     OIC_LOG(DEBUG, TAG, "IN");
-    CAEDRSendUnicastMessage(remoteAddress, (const char*) data, dataLength);
+
+    CAResult_t result = CAEDRSendUnicastMessage(remoteAddress, data, dataLength);
     OIC_LOG(DEBUG, TAG, "OUT");
-    return CA_STATUS_OK;
+    return result;
 }
 
-CAResult_t CAEDRClientSendMulticastData(const char *serviceUUID, const void *data,
-                                        uint32_t dataLength, uint32_t *sentLength)
+CAResult_t CAEDRClientSendMulticastData(const uint8_t *data, uint32_t dataLength)
 {
+    VERIFY_NON_NULL(data, TAG, "data is null");
     OIC_LOG(DEBUG, TAG, "IN");
-    CAEDRSendMulticastMessage((const char*) data, dataLength);
+
+    CAResult_t result = CAEDRSendMulticastMessage(data, dataLength);
     OIC_LOG(DEBUG, TAG, "OUT");
-    return CA_STATUS_OK;
+    return result;
 }
 
 // It will be updated when android EDR support is added
-void CAEDRClientUnsetCallbacks(void)
+void CAEDRClientUnsetCallbacks()
 {
     OIC_LOG(DEBUG, TAG, "IN");
 
@@ -221,7 +230,7 @@ void CAEDRClientUnsetCallbacks(void)
 }
 
 // It will be updated when android EDR support is added
-void CAEDRClientDisconnectAll(void)
+void CAEDRClientDisconnectAll()
 {
     OIC_LOG(DEBUG, TAG, "IN");
 
@@ -498,6 +507,78 @@ 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;
+    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;
+    }
+
+    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()
@@ -506,16 +587,18 @@ void CAEDRCoreJniInit()
     g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
 }
 
-CAResult_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 CA_STATUS_OK;
+    CAResult_t result = CAEDRSendUnicastMessageImpl(address, data, dataLen);
+    return result;
 }
 
-CAResult_t CAEDRSendMulticastMessage(const char* data, uint32_t dataLen)
+CAResult_t CAEDRSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
 {
+    VERIFY_NON_NULL(data, TAG, "data is null");
     OIC_LOG_V(DEBUG, TAG, "CAEDRSendMulticastMessage(%s)", data);
 
     bool isAttached = false;
@@ -534,7 +617,12 @@ CAResult_t CAEDRSendMulticastMessage(const char* data, uint32_t dataLen)
         isAttached = true;
     }
 
-    CAEDRSendMulticastMessageImpl(env, data, dataLen);
+    CAResult_t result = CAEDRSendMulticastMessageImpl(env, data, dataLen);
+    if(CA_STATUS_OK != result)
+    {
+        OIC_LOG(ERROR, TAG, "CAEDRSendMulticastMessage - could not send multicast message");
+        return result;
+    }
 
     OIC_LOG(DEBUG, TAG, "sent data");
 
@@ -582,10 +670,13 @@ void CAEDRGetLocalAddress(char **address)
             {
                 (*g_jvm)->DetachCurrentThread(g_jvm);
             }
+            (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
+            (*env)->DeleteLocalRef(env, jni_address);
             return;
         }
 
         (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
+        (*env)->DeleteLocalRef(env, jni_address);
     }
 
     OIC_LOG_V(DEBUG, TAG, "Local Address : %s", *address);
@@ -595,8 +686,10 @@ void CAEDRGetLocalAddress(char **address)
     }
 }
 
-CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const char* data, uint32_t dataLen)
+CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const uint8_t* data, uint32_t dataLen)
 {
+    VERIFY_NON_NULL(address, TAG, "address is null");
+    VERIFY_NON_NULL(data, TAG, "data is null");
     OIC_LOG_V(DEBUG, TAG, "CAEDRSendUnicastMessageImpl, address: %s, data: %s", address, data);
 
     bool isAttached = false;
@@ -635,8 +728,7 @@ CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const char* data, ui
                                                      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(DEBUG, TAG, "[EDR][Native] start to check device");
         // get name, address from BT device
@@ -648,13 +740,12 @@ CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const char* data, ui
             const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
             OIC_LOG_V(DEBUG, TAG, "[EDR][Native] getBondedDevices: ~~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, "[EDR][Native] remoteAddress is null");
@@ -662,31 +753,36 @@ CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const char* data, ui
             {
                 (*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;
         }
-        if (!address)
-        {
-            OIC_LOG(ERROR, TAG, "[EDR][Native] address is null");
-            if (isAttached)
-            {
-                (*g_jvm)->DetachCurrentThread(g_jvm);
-            }
-            (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
-            return CA_STATUS_INVALID_PARAM;
-        }
+        OIC_LOG_V(DEBUG, TAG,
+                  "[EDR][Native] getBondedDevices: ~~device address is %s", remoteAddress);
+
         // find address
         if (!strcmp(remoteAddress, address))
         {
-            CAResult_t res = 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)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
+                (*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);
     }
 
+    (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
+    (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
+
     if (isAttached)
     {
         (*g_jvm)->DetachCurrentThread(g_jvm);
@@ -695,8 +791,9 @@ CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const char* data, ui
     return CA_STATUS_OK;
 }
 
-CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const char* data, uint32_t dataLen)
+CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, uint32_t dataLen)
 {
+    VERIFY_NON_NULL(data, TAG, "data is null");
     OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %s, %d", data, dataLen);
 
     // get bonded device list
@@ -714,8 +811,7 @@ CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const char* data, uint32_t
                                                      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);
@@ -726,32 +822,42 @@ CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const char* data, uint32_t
             const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
             OIC_LOG_V(DEBUG, TAG, "[EDR][Native] getBondedDevices: ~~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);
+        (*env)->DeleteLocalRef(env, j_obj_device);
         OIC_LOG_V(DEBUG, TAG,
                   "[EDR][Native] getBondedDevices: ~~device address is %s", remoteAddress);
 
         // find address
-        CAResult_t res = 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)
         {
-            OIC_LOG_V(DEBUG, TAG, "[EDR][Native] Send data has failed : %s", remoteAddress);
+            OIC_LOG_V(ERROR, TAG, "CASendMulticastMessageImpl, failed to send message to : %s",
+                      remoteAddress);
+            g_edrErrorHandler(remoteAddress, data, dataLen, res);
             continue;
         }
     }
 
+    (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
+    (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
+
     return CA_STATUS_OK;
 }
 
 /**
  * EDR Method
  */
-CAResult_t 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)
 {
+    VERIFY_NON_NULL(address, TAG, "address is null");
+    VERIFY_NON_NULL(data, TAG, "data is null");
     OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btSendData logic start : %s, %d", data, dataLength);
 
     if (!CAEDRNativeIsEnableBTAdapter(env))
@@ -765,18 +871,10 @@ CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const char *dat
         // connect before send data
         OIC_LOG(DEBUG, TAG, "[EDR][Native] connect before send data");
 
-        if (NULL == address)
+        CAResult_t res = CAEDRNativeConnect(env, address);
+        if (CA_STATUS_OK != res)
         {
-            OIC_LOG(ERROR, TAG, "[EDR][Native] remote address is empty");
-            return CA_STATUS_INVALID_PARAM;
-        }
-        else
-        {
-            CAResult_t res = CAEDRNativeConnect(env, address, id);
-            if (CA_STATUS_OK != res)
-            {
-                return res;
-            }
+            return res;
         }
     }
 
@@ -797,6 +895,7 @@ CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const char *dat
             if (!jni_mid_getOutputStream)
             {
                 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_mid_getOutputStream is null");
+                (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
                 return CA_STATUS_FAILED;
             }
 
@@ -806,6 +905,7 @@ CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const char *dat
             if (!jni_obj_socket)
             {
                 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_socket is not available");
+                (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
                 return CA_STATUS_FAILED;
             }
 
@@ -814,6 +914,7 @@ CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const char *dat
             if (!jni_obj_outputStream)
             {
                 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_obj_outputStream is null");
+                (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
                 return CA_STATUS_FAILED;
             }
 
@@ -823,6 +924,8 @@ CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const char *dat
             if (!jni_cid_OutputStream)
             {
                 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_cid_OutputStream is null");
+                (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+                (*env)->DeleteLocalRef(env, jni_obj_outputStream);
                 return CA_STATUS_FAILED;
             }
 
@@ -831,16 +934,23 @@ CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const char *dat
             if (!jni_mid_write)
             {
                 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: 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);
+            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)->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(ERROR, TAG, "[EDR][Native] btSendData: Write Error!!!");
@@ -867,8 +977,9 @@ CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const char *dat
     return CA_STATUS_OK;
 }
 
-CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address, uint32_t id)
+CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address)
 {
+    VERIFY_NON_NULL(address, TAG, "address is null");
     OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect..");
 
     if (!CAEDRNativeIsEnableBTAdapter(env))
@@ -891,6 +1002,7 @@ CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address, uint32_t id)
     if (!jni_mid_getDefaultAdapter)
     {
         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_getDefaultAdapter is null");
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
         return CA_STATUS_FAILED;
     }
 
@@ -899,6 +1011,7 @@ CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address, uint32_t id)
     if (!jni_obj_BTAdapter)
     {
         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_BTAdapter is null");
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
         return CA_STATUS_FAILED;
     }
 
@@ -906,15 +1019,19 @@ CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address, uint32_t id)
     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(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_getRemoteDevice is null");
+        (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
         return CA_STATUS_FAILED;
     }
 
     jstring jni_address = (*env)->NewStringUTF(env, address);
     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(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_remoteBTDevice is null");
@@ -926,15 +1043,18 @@ CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address, uint32_t id)
     if (!jni_cid_BluetoothDevice)
     {
         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: 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;");
+    (*env)->DeleteLocalRef(env, jni_cid_BluetoothDevice);
     if (!jni_mid_createSocket)
     {
         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_createSocket is null");
+        (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
         return CA_STATUS_FAILED;
     }
 
@@ -943,6 +1063,7 @@ CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address, uint32_t id)
     if (!jni_cid_uuid)
     {
         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_uuid is null");
+        (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
         return CA_STATUS_FAILED;
     }
 
@@ -951,6 +1072,8 @@ CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address, uint32_t id)
     if (!jni_mid_fromString)
     {
         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_fromString is null");
+        (*env)->DeleteLocalRef(env, jni_cid_uuid);
+        (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
         return CA_STATUS_FAILED;
     }
 
@@ -958,18 +1081,25 @@ CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address, uint32_t id)
     if (!jni_uuid)
     {
         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: 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, "[EDR][Native] btConnect: 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);
+    (*env)->DeleteLocalRef(env, jni_obj_uuid);
+    (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
     if (!jni_obj_BTSocket)
     {
         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_BTSocket is null");
@@ -981,13 +1111,16 @@ CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address, uint32_t id)
     if (!jni_cid_BTSocket)
     {
         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: 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");
+    (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
     if (!jni_mid_connect)
     {
         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_connect is null");
+        (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
         return CA_STATUS_FAILED;
     }
 
@@ -1007,10 +1140,13 @@ CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address, uint32_t id)
     if (!jni_socket)
     {
         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: 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
@@ -1023,8 +1159,9 @@ CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address, uint32_t id)
     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)
@@ -1074,3 +1211,8 @@ void CAEDRInitializeClient(ca_thread_pool_t handle)
     CAEDRInitialize(handle);
     OIC_LOG(DEBUG, TAG, "OUT");
 }
+
+void CAEDRSetErrorHandler(CAEDRErrorHandleCallback errorHandleCallback)
+{
+    g_edrErrorHandler = errorHandleCallback;
+}