replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_edr_adapter / android / caedrclient.c
index 25fe644..d29de99 100644 (file)
@@ -1,22 +1,22 @@
 /******************************************************************
-*
-* 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.
-*
-******************************************************************/
+ *
+ * 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 <stdio.h>
 #include <string.h>
 #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 "octhread.h"
 #include "uarraylist.h"
 #include "caadapterutils.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 MAX_PDU_BUFFER = 1024;
-
-static u_arraylist_t *g_deviceStateList = NULL;
-static u_arraylist_t *g_deviceObjectList = NULL;
-
-static u_thread_pool_t g_threadPoolHandle = 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 g_context;
 
-static jbyteArray g_sendBuffer;
-
 /**
- * @var g_mutexSocketListManager
- * @brief Mutex to synchronize socket list update
+ * @var g_mutexStateList
+ * @brief Mutex to synchronize device state list
  */
-static u_mutex g_mutexSocketListManager;
-
-// server socket instance
-static jobject g_serverSocketObject = NULL;
+static oc_mutex g_mutexStateList = NULL;
 
 /**
- * @var g_mutexUnicastServer
- * @brief Mutex to synchronize unicast server
+ * @var g_mutexObjectList
+ * @brief Mutex to synchronize device object list
  */
-static u_mutex g_mutexUnicastServer = NULL;
+static oc_mutex g_mutexObjectList = NULL;
 
 /**
- * @var g_stopUnicast
- * @brief Flag to control the Receive Unicast Data Thread
+ * @var g_edrErrorHandler
+ * @brief Error callback to update error in EDR
  */
-static bool g_stopUnicast = false;
+static CAEDRErrorHandleCallback g_edrErrorHandler = NULL;
 
 /**
- * @var g_mutexMulticastServer
- * @brief Mutex to synchronize secure multicast server
+ * implement for BT-EDR adapter common method
  */
-static u_mutex g_mutexMulticastServer = NULL;
+CAResult_t CAEDRGetInterfaceInformation(CAEndpoint_t **info)
+{
+    OIC_LOG(DEBUG, TAG, "IN - CAEDRGetInterfaceInformation");
 
-/**
- * @var g_stopMulticast
- * @brief Flag to control the Receive Multicast Data Thread
- */
-static bool g_stopMulticast = false;
+    if (!info)
+    {
+        OIC_LOG(ERROR, TAG, "endpoint info is null");
+        return CA_STATUS_INVALID_PARAM;
+    }
 
-/**
- * @var g_stopAccept
- * @brief Flag to control the Accept Thread
- */
-static bool g_stopAccept = false;
+    char *macAddress = NULL;
+    CAResult_t ret = CAEDRGetInterfaceInfo(&macAddress);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG_V(ERROR, TAG, "Failed to get interface info [%d]", ret);
+        OICFree(macAddress);
+        return ret;
+    }
 
-typedef struct send_data {
-    char* address;
-    char* data;
-    uint32_t id;
-} data_t;
+    if (!macAddress)
+    {
+        OIC_LOG(ERROR, TAG, "mac address is null");
+        return CA_STATUS_FAILED;
+    }
+    OIC_LOG_V(DEBUG, TAG, "address : %s", macAddress);
 
-/**
- @brief Thread context information for unicast, multicast and secured unicast server
- */
-typedef struct
-{
-    bool *stopFlag;
-    CAAdapterServerType_t type;
-} CAAdapterReceiveThreadContext_t;
+    // Create local endpoint using util function
+    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!");
+        OICFree(macAddress);
+        return CA_STATUS_FAILED;
+    }
 
-typedef struct
-{
-    bool *stopFlag;
-} CAAdapterAcceptThreadContext_t;
+    // 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);
+        CAFreeEndpoint(endpoint);
+        return CA_MEMORY_ALLOC_FAILED;
+    }
+    *netInfo = *endpoint;
+    *info = netInfo;
 
+    OICFree(macAddress);
+    CAFreeEndpoint(endpoint);
 
-// TODO: It will be updated when android EDR support is added
-CAResult_t CAEDRGetInterfaceInformation(CALocalConnectivity_t **info)
-{
-    OIC_LOG(DEBUG, TAG, "IN");
-
-    OIC_LOG(DEBUG, TAG, "OUT");
+    OIC_LOG(DEBUG, TAG, "OUT - CAEDRGetInterfaceInformation");
     return CA_STATUS_OK;
 }
 
@@ -129,42 +137,42 @@ void CAEDRClientTerminate()
     OIC_LOG(DEBUG, TAG, "OUT");
 }
 
-CAResult_t CAEDRManagerReadData(void)
+CAResult_t CAEDRManagerReadData()
 {
     OIC_LOG(DEBUG, TAG, "IN");
+
     OIC_LOG(DEBUG, TAG, "OUT");
     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)
 {
-    OIC_LOG(DEBUG, TAG, "IN");
-    CAEDRSendUnicastMessage(remoteAddress, (const char*) data, dataLength);
-    OIC_LOG(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, const void *data,
-                                        uint32_t dataLength, uint32_t *sentLength)
+CAResult_t CAEDRClientSendMulticastData(const uint8_t *data, uint32_t dataLength)
 {
-    OIC_LOG(DEBUG, TAG, "IN");
-    CAEDRSendMulticastMessage((const char*) data, dataLength);
-    OIC_LOG(DEBUG, TAG, "OUT");
-    return CA_STATUS_OK;
+    VERIFY_NON_NULL(data, TAG, "data is null");
+
+    CAResult_t result = CAEDRSendMulticastMessage(data, dataLength);
+    return result;
 }
 
-// TODO: It will be updated when android EDR support is added
-void CAEDRClientUnsetCallbacks(void)
+// It will be updated when android EDR support is added
+void CAEDRClientUnsetCallbacks()
 {
     OIC_LOG(DEBUG, TAG, "IN");
 
     OIC_LOG(DEBUG, TAG, "OUT");
 }
 
-// TODO: It will be updated when android EDR support is added
-void CAEDRClientDisconnectAll(void)
+// It will be updated when android EDR support is added
+void CAEDRClientDisconnectAll()
 {
     OIC_LOG(DEBUG, TAG, "IN");
 
@@ -173,170 +181,121 @@ void CAEDRClientDisconnectAll(void)
 
 CAResult_t CAEDRGetAdapterEnableState(bool *state)
 {
-    OIC_LOG(DEBUG, TAG, "IN");
+    VERIFY_NON_NULL(state, TAG, "state is null");
+
     if (!g_jvm)
     {
         OIC_LOG(ERROR, TAG, "g_jvm is null");
         return CA_STATUS_INVALID_PARAM;
     }
-    jboolean isAttached = JNI_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(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(DEBUG, TAG, "AttachCurrentThread failed");
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
             return CA_STATUS_INVALID_PARAM;
         }
-        isAttached = JNI_TRUE;
+        isAttached = true;
     }
+
+    *state = false;
     jboolean ret = CAEDRNativeIsEnableBTAdapter(env);
-    if(ret)
+    if (ret)
     {
         *state = true;
     }
-    else
-    {
-        *state = false;
-    }
 
-    if(isAttached)
+    if (isAttached)
+    {
         (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
 
-    OIC_LOG(DEBUG, TAG, "OUT");
     return CA_STATUS_OK;
 }
 
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//FIXME getting context
-
-void CAEDRJniSetContext(jobject context)
+void CAEDRJniInitContext()
 {
-    OIC_LOG(DEBUG, TAG, "caedrSetObject");
-
-    if (!context)
-    {
-        OIC_LOG(ERROR, TAG, "context is null");
-        return;
-    }
-    jboolean isAttached = JNI_FALSE;
-    JNIEnv* env;
-    jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6);
-    if(res != JNI_OK)
-    {
-        OIC_LOG(DEBUG, TAG, "CAEDRInitialize - Could not get JNIEnv pointer");
-        res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
+    OIC_LOG(DEBUG, TAG, "CAEDRJniInitContext");
 
-        if(res != JNI_OK)
-        {
-            OIC_LOG(DEBUG, TAG, "AttachCurrentThread failed");
-            return;
-        }
-        isAttached = JNI_TRUE;
-    }
-
-    g_context = (*env)->NewGlobalRef(env, context);
-
-    if(isAttached)
-        (*g_jvm)->DetachCurrentThread(g_jvm);
+    g_context = (jobject) CANativeJNIGetContext();
 }
 
-void CAEDRCreateJNIInterfaceObject(jobject context)
+CAResult_t CAEDRCreateJNIInterfaceObject(jobject context)
 {
-    JNIEnv* env;
-    OIC_LOG(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(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(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(DEBUG, TAG, "[EDRCore] Could not get getApplicationContext method");
-        return;
+        OIC_LOG(ERROR, TAG, "Could not get application context");
+        return CA_STATUS_FAILED;
     }
 
-    jobject gApplicationContext = (*env)->CallObjectMethod(env, context,
-            getApplicationContextMethod);
-    OIC_LOG_V(DEBUG, TAG,
-            "[WIFICore] Saving Android application context object %p", gApplicationContext);
-
-   //Create WiFiInterface instance
-    jclass WiFiJniInterface = (*env)->FindClass(env, "com/iotivity/jar/CAEDRInterface");
-    if (!WiFiJniInterface)
+    //Create EDRJniInterface instance
+    jclass EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
+    if (!EDRJniInterface)
     {
-        OIC_LOG(DEBUG, TAG, "[EDRCore] Could not get CAWiFiInterface class");
-        return;
+        OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
+        return CA_STATUS_FAILED;
     }
 
-    jmethodID WiFiInterfaceConstructorMethod = (*env)->GetMethodID(env,
-            WiFiJniInterface, "<init>", "(Landroid/content/Context;)V");
-    if (!WiFiInterfaceConstructorMethod)
+    jmethodID EDRInterfaceConstructorMethod = (*env)->GetMethodID(env, EDRJniInterface, "<init>",
+                                                                  "(Landroid/content/Context;)V");
+    if (!EDRInterfaceConstructorMethod)
     {
-        OIC_LOG(ERROR, TAG, "[EDRCore] Could not get CAWiFiInterface constructor method");
-        return;
+        OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface constructor method");
+        return CA_STATUS_FAILED;
     }
 
-    (*env)->NewObject(env, WiFiJniInterface, WiFiInterfaceConstructorMethod, gApplicationContext);
-    OIC_LOG(DEBUG, TAG, "[EDRCore] Create CAWiFiInterface instance");
-    OIC_LOG(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 (g_mutexUnicastServer)
+    if (g_mutexStateList)
     {
-        u_mutex_free(g_mutexUnicastServer);
-        g_mutexUnicastServer = NULL;
+        oc_mutex_free(g_mutexStateList);
+        g_mutexStateList = NULL;
     }
 
-    if (g_mutexMulticastServer)
+    if (g_mutexObjectList)
     {
-        u_mutex_free(g_mutexMulticastServer);
-        g_mutexMulticastServer = NULL;
+        oc_mutex_free(g_mutexObjectList);
+        g_mutexObjectList = NULL;
     }
-
-    if(g_mutexSocketListManager)
-    {
-        u_mutex_free(g_mutexSocketListManager);
-        g_mutexSocketListManager = NULL;
-    }
-
-    OIC_LOG(DEBUG, TAG, "OUT");
 }
 
 static CAResult_t CAEDRCreateMutex()
 {
-    OIC_LOG(DEBUG, TAG, "IN");
-
-    g_mutexUnicastServer = u_mutex_new();
-    if (!g_mutexUnicastServer)
-    {
-        OIC_LOG(ERROR, TAG, "Failed to created mutex!");
-        return CA_STATUS_FAILED;
-    }
-
-    g_mutexMulticastServer = u_mutex_new();
-    if (!g_mutexMulticastServer)
+    g_mutexStateList = oc_mutex_new();
+    if (!g_mutexStateList)
     {
         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
 
@@ -344,8 +303,8 @@ static CAResult_t CAEDRCreateMutex()
         return CA_STATUS_FAILED;
     }
 
-    g_mutexSocketListManager = u_mutex_new();
-    if (!g_mutexSocketListManager)
+    g_mutexObjectList = oc_mutex_new();
+    if (!g_mutexObjectList)
     {
         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
 
@@ -353,132 +312,227 @@ 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");
 
-    g_threadPoolHandle = handle;
+    CAEDRCoreJniInit();
+
+    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 = JNI_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(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(DEBUG, TAG, "AttachCurrentThread failed");
-            return;
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
+            return CA_STATUS_NOT_INITIALIZED;
         }
-        isAttached = JNI_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);
+        (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
     }
+    (*env)->DeleteLocalRef(env, jni_address);
 
+    oc_mutex_lock(g_mutexStateList);
     CAEDRNativeCreateDeviceStateList();
+    oc_mutex_unlock(g_mutexStateList);
+
+    oc_mutex_lock(g_mutexObjectList);
     CAEDRNativeCreateDeviceSocketList();
+    oc_mutex_unlock(g_mutexObjectList);
 
-    if(isAttached)
+    if (isAttached)
+    {
         (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
 
- //   CAEDRCreateJNIInterfaceObject(gContext); /* create java CAEDRInterface instance*/
+    if (g_context)
+    {
+        CAEDRCreateJNIInterfaceObject(g_context); /* create java CaEdrInterface instance*/
+    }
 
     OIC_LOG(DEBUG, TAG, "OUT");
+
+    return result;
 }
 
 void CAEDRTerminate()
 {
     OIC_LOG(DEBUG, TAG, "CAEDRTerminate");
 
-    jboolean isAttached = JNI_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(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(DEBUG, TAG, "AttachCurrentThread failed");
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
             return;
         }
-        isAttached = JNI_TRUE;
+        isAttached = true;
     }
 
-    g_stopAccept = true;
-    g_stopMulticast = true;
-    g_stopUnicast = true;
-
-    if(isAttached)
+    if (isAttached)
+    {
         (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
 
-    if(g_context)
+    if (g_context)
     {
         (*env)->DeleteGlobalRef(env, g_context);
+        g_context = NULL;
     }
+
+    CAEDRNativeSocketCloseToAll(env);
+
     // delete mutex
     CAEDRDestroyMutex();
 
     CAEDRNativeRemoveAllDeviceState();
     CAEDRNativeRemoveAllDeviceSocket(env);
+    CAEDRDestroyJniInterface();
 }
 
-void CAEDRCoreJniInit(JNIEnv *env, JavaVM *jvm)
+CAResult_t CAEDRDestroyJniInterface()
 {
-    OIC_LOG(DEBUG, TAG, "CAEdrClientJniInit");
-    g_jvm = jvm;
+    OIC_LOG(DEBUG, TAG, "CAEDRDestroyJniInterface");
+
+    if (!g_jvm)
+    {
+        OIC_LOG(ERROR, TAG, "g_jvm is null");
+        return CA_STATUS_FAILED;
+    }
 
-    CAEDRServerJniInit(env, jvm);
+    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;
+    }
+
+    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(DEBUG, TAG, "CAEdrClientJniInit");
+    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)
 {
-    OIC_LOG_V(DEBUG, TAG, "CAEDRSendMulticastMessage(%s)", data);
+    VERIFY_NON_NULL(data, TAG, "data is null");
 
-    jboolean isAttached = JNI_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(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(DEBUG, TAG, "AttachCurrentThread failed");
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
             return CA_STATUS_INVALID_PARAM;
         }
-        isAttached = JNI_TRUE;
+        isAttached = true;
     }
 
-    CAEDRSendMulticastMessageImpl(env, data, dataLen);
-
-    OIC_LOG(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(DEBUG, TAG, "DetachCurrentThread");
         (*g_jvm)->DetachCurrentThread(g_jvm);
@@ -496,455 +550,549 @@ CAResult_t CAEDRGetInterfaceInfo(char **address)
 
 void CAEDRGetLocalAddress(char **address)
 {
-    jboolean isAttached = JNI_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(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(DEBUG, TAG, "AttachCurrentThread failed");
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
             return;
         }
-        isAttached = JNI_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)
+    {
         (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
 }
 
-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)
 {
-    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 = JNI_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(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(DEBUG, TAG, "AttachCurrentThread failed");
+            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");
-    if(g_sendBuffer)
-    {
-        (*env)->DeleteGlobalRef(env, g_sendBuffer);
-    }
-    jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
-    (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*)data);
-    g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
+    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(DEBUG, TAG, "[EDR][Native] jni_arrayPairedDevices is empty");
+        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(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);
-
-        if (!remoteAddress) {
-            OIC_LOG(ERROR, TAG, "[EDR][Native] remoteAddress is null");
-            if (isAttached)
-                (*g_jvm)->DetachCurrentThread(g_jvm);
-            return CA_STATUS_INVALID_PARAM;
-        }
-        if (!address) {
-            OIC_LOG(ERROR, TAG, "[EDR][Native] address is null");
+        (*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, 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);
     }
 
+    (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
+    (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
+
     if (isAttached)
+    {
         (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
 
     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)
 {
-    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(DEBUG, TAG, "[EDR][Native] jni_arrayPairedDevices is empty");
+        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, i);
+        (*env)->DeleteLocalRef(env, j_obj_device);
+        (*env)->DeleteLocalRef(env, j_str_name);
+        (*env)->DeleteLocalRef(env, j_str_address);
     }
 
+    (*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 id)
+CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const uint8_t *data,
+                               uint32_t dataLength)
 {
-    OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData logic start");
+    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(STATE_DISCONNECTED == CAEDRIsConnectedDevice(address))
+    if (!CAEDRNativeIsEnableBTAdapter(env))
+    {
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return CA_ADAPTER_NOT_ENABLED;
+    }
+
+    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)
+        CAResult_t res = CAEDRNativeConnect(env, address);
+        if (CA_STATUS_OK != res)
         {
-            OIC_LOG(ERROR, TAG, "[EDR][Native] remote address is empty");
-            return;
-        }
-        else
-        {
-            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(ERROR, 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(ERROR, 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(ERROR, 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(ERROR, 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(ERROR, 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(ERROR, 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;
-            int length = strlen(data);
-            jbuf = (*env)->NewByteArray(env, length);
-            (*env)->SetByteArrayRegion(env, jbuf, 0, length, (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) length);
+            (*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(ERROR, TAG, "[EDR][Native] btSendData: Write Error!!!");
+                OIC_LOG(ERROR, TAG, "Failed to write data in outputStram");
+                CALogSendStateInfo(CA_ADAPTER_RFCOMM_BTEDR, address, 0, dataLength, false, NULL);
                 (*env)->ExceptionDescribe(env);
                 (*env)->ExceptionClear(env);
-                return;
+                return CA_STATUS_FAILED;
             }
 
-            OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: Write Success");
-
-            // remove socket to list
-            CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
-
-            // update state
-            CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
+            OIC_LOG_V(INFO, TAG, "EDR sendTo is successful: %u bytes, to %s",
+                      dataLength, address);
+            CALogSendStateInfo(CA_ADAPTER_RFCOMM_BTEDR, address, 0, dataLength, true, NULL);
         }
         else
         {
+            OIC_LOG(ERROR, TAG, "error!!");
+            CALogSendStateInfo(CA_ADAPTER_RFCOMM_BTEDR, address, 0, dataLength, false, NULL);
             (*env)->ExceptionDescribe(env);
             (*env)->ExceptionClear(env);
-            OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: error!!");
-            return;
+            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))
+    {
+        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)
-    {
-        OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: jni_mid_getRemoteDevice is null");
-        return;
+    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, "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",
+    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;
+    (*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;
     }
 
-    jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid,
-            jni_mid_fromString, OIC_EDR_SERVICE_ID);
-    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!!!");
+        CALogSendStateInfo(CA_ADAPTER_RFCOMM_BTEDR, address, 0, 0, false, "Connect has 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;
+    }
+    oc_mutex_lock(g_mutexObjectList);
     CAEDRNativeAddDeviceSocketToList(env, jni_socket);
+    (*env)->DeleteGlobalRef(env, jni_socket);
+    (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
+    oc_mutex_unlock(g_mutexObjectList);
 
     // update state
+    oc_mutex_lock(g_mutexStateList);
     CAEDRUpdateDeviceState(STATE_CONNECTED, address);
+    oc_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(ERROR, 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(ERROR, 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(ERROR, 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;
@@ -954,445 +1102,20 @@ void CAEDRNativeSocketClose(JNIEnv *env, const char *address, uint32_t id)
     CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
 
     // update state
+    oc_mutex_lock(g_mutexStateList);
     CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
+    oc_mutex_unlock(g_mutexStateList);
 
-    OIC_LOG(DEBUG, TAG, "[EDR][Native] close: disconnected");
+    OIC_LOG_V(DEBUG, TAG, "disconnected with [%s]", address);
 }
 
-
-/**
- * BT State List
- */
-void CAEDRNativeCreateDeviceStateList()
+CAResult_t CAEDRClientInitialize()
 {
-    OIC_LOG(DEBUG, TAG, "[EDR][Native] CAEDRNativeCreateDeviceStateList");
-
-    // create new object array
-    if (g_deviceStateList == NULL)
-    {
-        OIC_LOG(DEBUG, TAG, "Create device list");
-
-        g_deviceStateList = u_arraylist_create();
-    }
-}
-
-void CAEDRUpdateDeviceState(CAConnectedState_t state, const char *address)
-{
-    state_t *newstate = (state_t*) OICCalloc(1, sizeof(state_t));
-    if (!newstate) {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] newstate is null");
-        return;
-    }
-    strcpy(newstate->address, address);
-    newstate->state = state;
-
-    CAEDRNativeAddDeviceStateToList(newstate);
+    CAResult_t result = CAEDRInitialize();
+    return result;
 }
 
-void CAEDRNativeAddDeviceStateToList(state_t *state)
+void CAEDRSetErrorHandler(CAEDRErrorHandleCallback errorHandleCallback)
 {
-    if(!state)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] device is null");
-        return;
-    }
-
-    if(!g_deviceStateList)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] gdevice_list is null");
-        return;
-    }
-
-    if(CAEDRNativeIsDeviceInList(state->address)) {
-        CAEDRNativeRemoveDevice(state->address); // delete previous state for update new state
-    }
-    u_arraylist_add(g_deviceStateList, state);          // update new state
-    OIC_LOG_V(DEBUG, TAG, "Set State Info to List : %d", state->state);
-}
-
-jboolean CAEDRNativeIsDeviceInList(const char* remoteAddress){
-
-    jint index;
-    if (!remoteAddress) {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] remoteAddress is null");
-        return JNI_TRUE;
-    }
-    for (index = 0; index < u_arraylist_length(g_deviceStateList); index++)
-    {
-        state_t* state = (state_t*) u_arraylist_get(g_deviceStateList, index);
-        if(!state)
-        {
-            OIC_LOG(ERROR, TAG, "[EDR][Native] state_t object is null");
-            return JNI_TRUE;
-        }
-
-        if(!strcmp(remoteAddress, state->address))
-        {
-            OIC_LOG(DEBUG, TAG, "the device is already set");
-            return JNI_TRUE;
-        }
-        else
-        {
-            continue;
-        }
-    }
-
-    OIC_LOG(DEBUG, TAG, "there are no the device in list.");
-    return JNI_FALSE;
-}
-
-void CAEDRNativeRemoveAllDeviceState()
-{
-    OIC_LOG(DEBUG, TAG, "CAEDRNativeRemoveAllDevices");
-
-    if(!g_deviceStateList)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceStateList is null");
-        return;
-    }
-
-    jint index;
-    for (index = 0; index < u_arraylist_length(g_deviceStateList); index++)
-    {
-        state_t* state = (state_t*) u_arraylist_get(g_deviceStateList, index);
-        if(!state)
-        {
-            OIC_LOG(DEBUG, TAG, "[EDR][Native] jarrayObj is null");
-            continue;
-        }
-        OICFree(state);
-    }
-
-    OICFree(g_deviceStateList);
-    g_deviceStateList = NULL;
-    return;
-}
-
-void CAEDRNativeRemoveDevice(const char *remoteAddress)
-{
-    OIC_LOG(DEBUG, TAG, "CAEDRNativeRemoveDeviceforStateList");
-
-    if(!g_deviceStateList)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceStateList is null");
-        return;
-    }
-    if (!remoteAddress) {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] remoteAddress is null");
-        return;
-    }
-
-    jint index;
-    for (index = 0; index < u_arraylist_length(g_deviceStateList); index++)
-    {
-        state_t* state = (state_t*) u_arraylist_get(g_deviceStateList, index);
-        if(!state)
-        {
-            OIC_LOG(DEBUG, TAG, "[EDR][Native] state_t object is null");
-            continue;
-        }
-
-        if(!strcmp(state->address, remoteAddress))
-        {
-            OIC_LOG_V(DEBUG, TAG, "[EDR][Native] remove state : %s", remoteAddress);
-            OICFree(state);
-
-            CAEDRReorderingDeviceList(index);
-            break;
-        }
-    }
-    return;
-}
-
-CAConnectedState_t CAEDRIsConnectedDevice(const char *remoteAddress)
-{
-    OIC_LOG(DEBUG, TAG, "CAEDRIsConnectedDevice");
-
-    if(!g_deviceStateList)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceStateList is null");
-        return STATE_DISCONNECTED;
-    }
-
-    jint index;
-    for (index = 0; index < u_arraylist_length(g_deviceStateList); index++)
-    {
-        state_t* state = (state_t*) u_arraylist_get(g_deviceStateList, index);
-        if(!state)
-        {
-            OIC_LOG(DEBUG, TAG, "[EDR][Native] state_t object is null");
-            continue;
-        }
-
-        if(!strcmp(state->address, remoteAddress))
-        {
-            OIC_LOG(DEBUG, TAG, "[EDR][Native] check whether it is connected or not");
-
-            return state->state;
-        }
-    }
-    return STATE_DISCONNECTED;
-}
-
-void CAEDRReorderingDeviceList(uint32_t index)
-{
-    if (index >= g_deviceStateList->length)
-    {
-        return;
-    }
-
-    if (index < g_deviceStateList->length - 1)
-    {
-        memmove(&g_deviceStateList->data[index], &g_deviceStateList->data[index + 1],
-                (g_deviceStateList->length - index - 1) * sizeof(void *));
-    }
-
-    g_deviceStateList->size--;
-    g_deviceStateList->length--;
-}
-
-/**
- * Device Socket Object List
- */
-void CAEDRNativeCreateDeviceSocketList()
-{
-    OIC_LOG(DEBUG, TAG, "[EDR][Native] CAEDRNativeCreateDeviceSocketList");
-
-    // create new object array
-    if (g_deviceObjectList == NULL)
-    {
-        OIC_LOG(DEBUG, TAG, "Create Device object list");
-
-        g_deviceObjectList = u_arraylist_create();
-    }
+    g_edrErrorHandler = errorHandleCallback;
 }
-
-void CAEDRNativeAddDeviceSocketToList(JNIEnv *env, jobject deviceSocket)
-{
-    OIC_LOG(DEBUG, TAG, "[EDR][Native] CANativeAddDeviceobjToList");
-
-    if(!deviceSocket)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] Device is null");
-        return;
-    }
-
-    if(!g_deviceObjectList)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceObjectList is null");
-        return;
-    }
-
-    jstring jni_remoteAddress = CAEDRNativeGetAddressFromDeviceSocket(env, deviceSocket);
-    if(!jni_remoteAddress)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] jni_remoteAddress is null");
-        return;
-    }
-
-    u_mutex_lock(g_mutexSocketListManager);
-
-    const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
-
-    if(!CAEDRNativeIsDeviceSocketInList(env, remoteAddress))
-    {
-        jobject gDeviceSocker = (*env)->NewGlobalRef(env, deviceSocket);
-        u_arraylist_add(g_deviceObjectList, gDeviceSocker);
-        OIC_LOG(DEBUG, TAG, "Set Socket Object to Array");
-    }
-
-    u_mutex_unlock(g_mutexSocketListManager);
-}
-
-jboolean CAEDRNativeIsDeviceSocketInList(JNIEnv *env, const char* remoteAddress)
-{
-    OIC_LOG(DEBUG, TAG, "[EDR][Native] CANativeIsDeviceObjInList");
-
-    jint index;
-
-    if (!remoteAddress) {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] remoteAddress is null");
-        return JNI_TRUE;
-    }
-    for (index = 0; index < u_arraylist_length(g_deviceObjectList); index++)
-    {
-
-        jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, index);
-        if(!jarrayObj)
-        {
-            OIC_LOG(DEBUG, TAG, "[EDR][Native] jarrayObj is null");
-            return JNI_TRUE;
-        }
-
-        jstring jni_setAddress = CAEDRNativeGetAddressFromDeviceSocket(env, jarrayObj);
-        if(!jni_setAddress)
-        {
-            OIC_LOG(DEBUG, TAG, "[EDR][Native] jni_setAddress is null");
-            return JNI_TRUE;
-        }
-
-        const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
-        if(!setAddress)
-        {
-            OIC_LOG(DEBUG, TAG, "[EDR][Native] setAddress is null");
-            return JNI_TRUE;
-        }
-
-        if(!strcmp(remoteAddress, setAddress))
-        {
-            OIC_LOG(DEBUG, TAG, "the device is already set");
-            return JNI_TRUE;
-        }
-        else
-        {
-            continue;
-        }
-    }
-
-    OIC_LOG(DEBUG, TAG, "there are no the Device obejct in list. we can add");
-    return JNI_FALSE;
-}
-
-void CAEDRNativeRemoveAllDeviceSocket(JNIEnv *env)
-{
-    OIC_LOG(DEBUG, TAG, "CANativeRemoveAllDeviceObjsList");
-
-    if(!g_deviceObjectList)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceObjectList is null");
-        return;
-    }
-
-    jint index;
-    for (index = 0; index < u_arraylist_length(g_deviceObjectList); index++)
-    {
-        jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, index);
-        if(!jarrayObj)
-        {
-            OIC_LOG(DEBUG, TAG, "[EDR][Native] jarrayObj is null");
-            return;
-        }
-        (*env)->DeleteGlobalRef(env, jarrayObj);
-    }
-
-    OICFree(g_deviceObjectList);
-    g_deviceObjectList = NULL;
-    return;
-}
-
-void CAEDRNativeRemoveDeviceSocket(JNIEnv *env, jobject deviceSocket)
-{
-    OIC_LOG(DEBUG, TAG, "CAEDRNativeRemoveDeviceSocket");
-
-    if(!g_deviceObjectList)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceObjectList is null");
-        return;
-    }
-
-    u_mutex_lock(g_mutexSocketListManager);
-
-    jint index;
-    for (index = 0; index < u_arraylist_length(g_deviceObjectList); index++)
-    {
-        jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, index);
-        if(!jarrayObj)
-        {
-            OIC_LOG(DEBUG, TAG, "[EDR][Native] jarrayObj is null");
-            continue;
-        }
-
-        jstring jni_setAddress = CAEDRNativeGetAddressFromDeviceSocket(env, jarrayObj);
-        if(!jni_setAddress)
-        {
-            OIC_LOG(DEBUG, TAG, "[EDR][Native] jni_setAddress is null");
-            continue;
-        }
-        const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
-
-        jstring jni_remoteAddress = CAEDRNativeGetAddressFromDeviceSocket(env, deviceSocket);
-        if(!jni_remoteAddress)
-        {
-            OIC_LOG(DEBUG, TAG, "[EDR][Native] jni_remoteAddress is null");
-            continue;
-        }
-        const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
-
-        if(!strcmp(setAddress, remoteAddress))
-        {
-            OIC_LOG_V(DEBUG, TAG, "[EDR][Native] remove object : %s", remoteAddress);
-            (*env)->DeleteGlobalRef(env, jarrayObj);
-
-            CAEDRReorderingDeviceSocketList(index);
-            break;
-        }
-    }
-    u_mutex_unlock(g_mutexSocketListManager);
-
-    OIC_LOG(DEBUG, TAG, "[EDR][Native] there are no target object");
-    return;
-}
-
-jobject CAEDRNativeGetDeviceSocket(uint32_t idx)
-{
-    OIC_LOG(DEBUG, TAG, "CAEDRNativeGetDeviceSocket");
-
-    if(idx < 0)
-    {
-        OIC_LOG(DEBUG, TAG, "[EDR][Native] index is not available");
-        return NULL;
-    }
-
-    if(!g_deviceObjectList)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceObjectList is null");
-        return NULL;
-    }
-
-    jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, idx);
-    if(!jarrayObj)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] jarrayObj is not available");
-        return NULL;
-    }
-    return jarrayObj;
-}
-
-uint32_t CAEDRGetSocketListLength()
-{
-    if(!g_deviceObjectList)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceObjectList is null");
-        return 0;
-    }
-
-    uint32_t length = u_arraylist_length(g_deviceObjectList);
-
-    return length;
-}
-
-void CAEDRReorderingDeviceSocketList(uint32_t index)
-{
-    if (index >= g_deviceObjectList->length)
-    {
-        return;
-    }
-
-    if (index < g_deviceObjectList->length - 1)
-    {
-        memmove(&g_deviceObjectList->data[index], &g_deviceObjectList->data[index + 1],
-                (g_deviceObjectList->length - index - 1) * sizeof(void *));
-    }
-
-    g_deviceObjectList->size--;
-    g_deviceObjectList->length--;
-}
-
-void CAEDRInitializeClient(u_thread_pool_t handle)
-{
-    OIC_LOG(DEBUG, TAG, "IN");
-    CAEDRInitialize(handle);
-    OIC_LOG(DEBUG, TAG, "OUT");
-}
-
-