code clean up for android edr
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_edr_adapter / android / caedrserver.c
index 645a2f2..3d4dcb6 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 "caedrserver.h"
 #include "logger.h"
 #include "oic_malloc.h"
-#include "uthreadpool.h" /* for thread pool */
-#include "umutex.h"
+#include "cathreadpool.h" /* for thread pool */
+#include "camutex.h"
 #include "uarraylist.h"
 #include "caadapterutils.h"
+#include "org_iotivity_ca_CaEdrInterface.h"
+#include "oic_string.h"
 
-//#define DEBUG_MODE
-#define TAG PCF("CA_EDR_SERVER")
+#define TAG PCF("OIC_CA_EDR_SERVER")
 
 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 char CLASSPATH_BT_SERVER_SOCKET[] = "android/bluetooth/BluetoothServerSocket";
 
-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;
+static ca_thread_pool_t g_threadPoolHandle = NULL;
 
 static JavaVM *g_jvm;
 
-static jbyteArray g_sendBuffer;
+/**
+ * Maximum CoAP over TCP header length
+ * to know the total data length.
+ */
+#define EDR_MAX_HEADER_LEN  6
 
 /**
- * @var g_mMutexSocketListManager
- * @brief Mutex to synchronize socket list update
+ * Mutex to synchronize receive server.
  */
-static u_mutex g_mutexSocketListManager;
+static ca_mutex g_mutexReceiveServer = NULL;
 
-// server socket instance
-static jobject g_serverSocketObject = NULL;
+/**
+ * Flag to control the Receive Unicast Data Thread.
+ */
+static bool g_stopUnicast = false;
 
 /**
- * @var g_mutexUnicastServer
- * @brief Mutex to synchronize unicast server
+ * Mutex to synchronize accept server.
  */
-static u_mutex g_mutexUnicastServer = NULL;
+static ca_mutex g_mutexAcceptServer = NULL;
 
 /**
- * @var g_stopUnicast
- * @brief Flag to control the Receive Unicast Data Thread
+ * Flag to control the Accept Thread.
  */
-static bool g_stopUnicast = false;
+static bool g_stopAccept = false;
 
 /**
- * @var g_mutexMulticastServer
- * @brief Mutex to synchronize secure multicast server
+ * Mutex to synchronize server socket.
  */
-static u_mutex g_mutexMulticastServer = NULL;
+static ca_mutex g_mutexServerSocket = NULL;
 
 /**
- * @var g_stopMulticast
- * @brief Flag to control the Receive Multicast Data Thread
+ * Flag to control the server socket.
  */
-static bool g_stopMulticast = false;
+static jobject g_serverSocket = NULL;
 
 /**
- * @var g_stopAccept
- * @brief Flag to control the Accept Thread
+ * Mutex to synchronize device state list.
  */
-static bool g_stopAccept = false;
+static ca_mutex g_mutexStateList = NULL;
 
-typedef struct send_data {
-    char* address;
-    char* data;
-    uint32_t id;
-} data_t;
+/**
+ * Mutex to synchronize device object list.
+ */
+static ca_mutex g_mutexObjectList = NULL;
 
 /**
- @brief Thread context information for unicast, multicast and secured unicast server
+ * Thread context information for unicast, multicast and secured unicast server.
  */
 typedef struct
 {
@@ -110,200 +105,266 @@ typedef struct
     bool *stopFlag;
 } CAAdapterAcceptThreadContext_t;
 
-// callback instance
-
 /**
- * @var g_EDRPacketReceivedCallback
- * @brief Maintains the callback to be notified when data received from remote Bluetooth device
+ * Maintains the callback to be notified when data received from remote
+ * Bluetooth device.
  */
-static CAEDRDataReceivedCallback g_EDRPacketReceivedCallback = NULL;
+static CAEDRDataReceivedCallback g_edrPacketReceivedCallback = NULL;
 
 static void CAReceiveHandler(void *data)
 {
-    OIC_LOG_V(DEBUG, TAG, "start CAReceiveHandler..");
-    OIC_LOG(DEBUG, TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "IN - CAReceiveHandler..");
     // Input validation
     VERIFY_NON_NULL_VOID(data, TAG, "Invalid thread context");
 
-    jboolean isAttached = JNI_FALSE;
+    bool isAttached = false;
     JNIEnv* env;
-    jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6);
-    if(res != JNI_OK)
+    jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
+    if (JNI_OK != res)
     {
-        OIC_LOG_V(DEBUG, TAG, "CAReceiveHandler - Could not get JNIEnv pointer");
+        OIC_LOG(DEBUG, TAG, "CAReceiveHandler - Could not get JNIEnv pointer");
         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
 
-        if(res != JNI_OK)
+        if (JNI_OK != res)
         {
-            OIC_LOG_V(DEBUG, TAG, "AttachCurrentThread failed");
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
             return;
         }
-        isAttached = JNI_TRUE;
+        isAttached = true;
     }
 
-    CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)data;
+    CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) data;
 
     while (true != *(ctx->stopFlag))
     {
-        uint32_t idx;
-
-        // if new socket object is added in socket list after below logic is ran.
-        // new socket will be started to read after next while loop
-        uint32_t length = CAEDRServerGetSocketListLength();
-        if (0 == length)
+        if (!CAEDRNativeIsEnableBTAdapter(env))
         {
-            OIC_LOG_V(DEBUG, TAG, "socket list is empty");
+            OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+            break;
         }
 
-        for (idx = 0; idx < length; idx++)
+        // if new socket object is added in socket list after below logic is ran.
+        // new socket will be started to read after next while loop
+        uint32_t length = CAEDRGetSocketListLength();
+        if (0 != length)
         {
-            OIC_LOG_V(DEBUG, TAG, "start CAEDRNativeReadData");
-            CAEDRNativeReadData(env, idx, ctx->type);
+            for (uint32_t idx = 0; idx < length; idx++)
+            {
+                CAEDRNativeReadData(env, idx);
+            }
         }
-
     }
 
-    if(isAttached)
+    if (isAttached)
+    {
         (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
 
-    if(ctx)
-        OICFree(ctx);
+    OICFree(ctx);
 
-    OIC_LOG(DEBUG, TAG, "OUT");
+    OIC_LOG(DEBUG, TAG, "OUT - CAReceiveHandler");
 }
 
 static void CAAcceptHandler(void *data)
 {
-    if (!data)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR] CAAcceptHandler: data is null");
-        return;
-    }
-    OIC_LOG(DEBUG, TAG, "[EDR] AcceptThread start");
+    OIC_LOG(DEBUG, TAG, "AcceptThread start");
+
+    VERIFY_NON_NULL_VOID(data, TAG, "data is null");
 
-    jboolean isAttached = JNI_FALSE;
+    bool isAttached = false;
     JNIEnv* env;
-    jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6);
-    if(res != JNI_OK)
+    jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
+    if (JNI_OK != res)
     {
-        OIC_LOG_V(DEBUG, TAG, "CAAcceptHandler - Could not get JNIEnv pointer");
+        OIC_LOG(DEBUG, TAG, "Could not get JNIEnv pointer");
         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
 
-        if(res != JNI_OK)
+        if (JNI_OK != res)
         {
-            OIC_LOG_V(DEBUG, TAG, "AttachCurrentThread failed");
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
             return;
         }
-        isAttached = JNI_TRUE;
+        isAttached = true;
     }
 
-    jobject jni_obj_BTSeverSocket = CAEDRNativeListen(env);
-    if (!jni_obj_BTSeverSocket)
+    jobject jni_obj_BTServerSocket = CAEDRNativeListen(env);
+    if (!jni_obj_BTServerSocket)
     {
-        OIC_LOG(ERROR, TAG, "[EDR] AcceptThread: jni_obj_BTSeverSocket is null");
+        OIC_LOG(ERROR, TAG, "jni_obj_BTServerSocket is null");
 
-        if(isAttached)
+        if (isAttached)
+        {
             (*g_jvm)->DetachCurrentThread(g_jvm);
+        }
 
         return;
     }
 
-    CAAdapterAcceptThreadContext_t *ctx = (CAAdapterAcceptThreadContext_t *)data;
+    ca_mutex_lock(g_mutexServerSocket);
+    g_serverSocket = (*env)->NewGlobalRef(env, jni_obj_BTServerSocket);
+    ca_mutex_unlock(g_mutexServerSocket);
+
+    CAAdapterAcceptThreadContext_t *ctx = (CAAdapterAcceptThreadContext_t *) data;
+
+    // it should be initialized for restart accept thread
+    ca_mutex_lock(g_mutexAcceptServer);
+    g_stopAccept = false;
+    ca_mutex_unlock(g_mutexAcceptServer);
 
     while (true != *(ctx->stopFlag))
     {
-        OIC_LOG(DEBUG, TAG, "[EDR] AcceptThread running");
-        CAEDRNativeAccept(env, jni_obj_BTSeverSocket);
+        // when BT state is changed with Off. its thread will be stopped
+        if (!CAEDRNativeIsEnableBTAdapter(env))
+        {
+            OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+            ca_mutex_lock(g_mutexAcceptServer);
+            g_stopAccept = true;
+            ca_mutex_unlock(g_mutexAcceptServer);
+            ca_mutex_lock(g_mutexServerSocket);
+            g_serverSocket = NULL;
+            ca_mutex_unlock(g_mutexServerSocket);
+        }
+        else
+        {
+            CAEDRNativeAccept(env, g_serverSocket);
+        }
     }
 
-    if(isAttached)
+    if (isAttached)
+    {
         (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
 
-    if(ctx)
-        OICFree(ctx);
+    OICFree(ctx);
 
-    OIC_LOG(DEBUG, TAG, "[EDR] AcceptThread finish");
+    OIC_LOG(DEBUG, TAG, "AcceptThread finish");
 
     return;
 }
 
+/**
+ * implement for adapter common method.
+ */
+CAResult_t CAEDRServerStart()
+{
+    if (!g_threadPoolHandle)
+    {
+        return CA_STATUS_NOT_INITIALIZED;
+    }
 
-// adapter common method
+    CAResult_t res = CAEDRServerStartAcceptThread();
+    if (CA_STATUS_OK == res)
+    {
+        res = CAEDRStartReceiveThread(false);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "failed to start receive thread");
+            CAEDRServerStop();
+            return CA_STATUS_FAILED;
+        }
+    }
 
-CAResult_t CAEDRServerStart(const char *serviceUUID, int32_t *serverFD, u_thread_pool_t handle)
-{
-    OIC_LOG_V(DEBUG, TAG, "IN");
-    CAEDRServerInitialize(handle);
-    // FIXME
-    CAEDRStartUnicastServer(NULL, false);
-    OIC_LOG_V(DEBUG, TAG, "OUT");
-    return CA_STATUS_OK;
+    return res;
 }
 
-CAResult_t CAEDRServerStop(int serverFD)
+CAResult_t CAEDRServerStop()
 {
-    OIC_LOG_V(DEBUG, TAG, "IN");
-    CAEDRStopUnicastServer(-1);
-    CAEDRStopMulticastServer(-1);
+    CAEDRStopReceiveThread();
+
+    ca_mutex_lock(g_mutexAcceptServer);
+    g_stopAccept = true;
+    ca_mutex_unlock(g_mutexAcceptServer);
+
+    if (!g_jvm)
+    {
+        OIC_LOG(DEBUG, 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(DEBUG, TAG, "Could not get JNIEnv pointer");
+        res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
 
-    g_stopAccept = TRUE;
-    g_stopMulticast = TRUE;
-    g_stopUnicast = TRUE;
+        if (JNI_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
+            return CA_STATUS_FAILED;
+        }
+        isAttached = true;
+    }
+
+    CAEDRNatvieCloseServerTask(env);
+
+    if (isAttached)
+    {
+        (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
 
-    OIC_LOG_V(DEBUG, TAG, "OUT");
     return CA_STATUS_OK;
 }
 
 void CAEDRSetPacketReceivedCallback(CAEDRDataReceivedCallback packetReceivedCallback)
 {
-    g_EDRPacketReceivedCallback = packetReceivedCallback;
+    g_edrPacketReceivedCallback = packetReceivedCallback;
 }
 
-/**
- * Destroy Mutex
- */
 static void CAEDRServerDestroyMutex()
 {
-    OIC_LOG(DEBUG, TAG, "IN");
+    if (g_mutexReceiveServer)
+    {
+        ca_mutex_free(g_mutexReceiveServer);
+        g_mutexReceiveServer = NULL;
+    }
 
-    if (g_mutexUnicastServer)
+    if (g_mutexAcceptServer)
     {
-        u_mutex_free(g_mutexUnicastServer);
-        g_mutexUnicastServer = NULL;
+        ca_mutex_free(g_mutexAcceptServer);
+        g_mutexAcceptServer = NULL;
     }
 
-    if (g_mutexMulticastServer)
+    if (g_mutexServerSocket)
     {
-        u_mutex_free(g_mutexMulticastServer);
-        g_mutexMulticastServer = NULL;
+        ca_mutex_free(g_mutexServerSocket);
+        g_mutexServerSocket = NULL;
     }
 
-    if(g_mutexSocketListManager)
+    if (g_mutexStateList)
     {
-        u_mutex_free(g_mutexSocketListManager);
-        g_mutexSocketListManager = NULL;
+        ca_mutex_free(g_mutexStateList);
+        g_mutexStateList = NULL;
     }
 
-    OIC_LOG(DEBUG, TAG, "OUT");
+    if (g_mutexObjectList)
+    {
+        ca_mutex_free(g_mutexObjectList);
+        g_mutexObjectList = NULL;
+    }
 }
 
-
-/*
- * Create Mutex
- */
 static CAResult_t CAEDRServerCreateMutex()
 {
-    OIC_LOG(DEBUG, TAG, "IN");
+    g_mutexReceiveServer = ca_mutex_new();
+    if (!g_mutexReceiveServer)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to created mutex!");
+        return CA_STATUS_FAILED;
+    }
 
-    g_mutexUnicastServer = u_mutex_new();
-    if (!g_mutexUnicastServer)
+    g_mutexAcceptServer = ca_mutex_new();
+    if (!g_mutexAcceptServer)
     {
         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
+
+        CAEDRServerDestroyMutex();
         return CA_STATUS_FAILED;
     }
 
-    g_mutexMulticastServer = u_mutex_new();
-    if (!g_mutexMulticastServer)
+    g_mutexServerSocket = ca_mutex_new();
+    if (!g_mutexServerSocket)
     {
         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
 
@@ -311,8 +372,17 @@ static CAResult_t CAEDRServerCreateMutex()
         return CA_STATUS_FAILED;
     }
 
-    g_mutexSocketListManager = u_mutex_new();
-    if (!g_mutexSocketListManager)
+    g_mutexStateList = ca_mutex_new();
+    if (!g_mutexStateList)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to created mutex!");
+
+        CAEDRServerDestroyMutex();
+        return CA_STATUS_FAILED;
+    }
+
+    g_mutexObjectList = ca_mutex_new();
+    if (!g_mutexObjectList)
     {
         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
 
@@ -320,39 +390,42 @@ static CAResult_t CAEDRServerCreateMutex()
         return CA_STATUS_FAILED;
     }
 
-    OIC_LOG(DEBUG, TAG, "OUT");
     return CA_STATUS_OK;
 }
 
-void CAEDRServerJniInit(JNIEnv *env, JavaVM* jvm)
+void CAEDRServerJniInit()
 {
-    OIC_LOG_V(DEBUG, TAG, "CAEDRServerJniInit");
-    g_jvm = jvm;
+    OIC_LOG(DEBUG, TAG, "CAEDRServerJniInit");
+    g_jvm = CANativeJNIGetJavaVM();
 }
 
-void CAEDRServerInitialize(u_thread_pool_t handle)
+CAResult_t CAEDRServerInitialize(ca_thread_pool_t handle)
 {
     OIC_LOG(DEBUG, TAG, "CAEDRServerInitialize");
+    VERIFY_NON_NULL(handle, TAG, "handle is NULL");
 
     g_threadPoolHandle = handle;
+    CAEDRServerJniInit();
 
-    // init mutex
-    CAEDRServerCreateMutex();
+    return CAEDRServerCreateMutex();
+}
 
-    jboolean isAttached = JNI_FALSE;
+CAResult_t CAEDRServerStartAcceptThread()
+{
+    bool isAttached = false;
     JNIEnv* env;
-    jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6);
-    if(res != JNI_OK)
+    jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
+    if (JNI_OK != res)
     {
-        OIC_LOG_V(DEBUG, TAG, "CAEDRServerInitialize - Could not get JNIEnv pointer");
+        OIC_LOG(DEBUG, TAG, "Could not get JNIEnv pointer");
         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
 
-        if(res != JNI_OK)
+        if (JNI_OK != res)
         {
-            OIC_LOG_V(DEBUG, TAG, "AttachCurrentThread failed");
-            return;
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
+            return CA_STATUS_FAILED;
         }
-        isAttached = JNI_TRUE;
+        isAttached = true;
     }
 
     jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
@@ -363,29 +436,36 @@ void CAEDRServerInitialize(u_thread_pool_t handle)
         (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
     }
 
-    CAEDRServerNativeCreateDeviceStateList();
-    CAEDRServerNativeCreateDeviceSocketList();
+    ca_mutex_lock(g_mutexStateList);
+    CAEDRNativeCreateDeviceStateList();
+    ca_mutex_unlock(g_mutexStateList);
 
-    if(isAttached)
+    ca_mutex_lock(g_mutexObjectList);
+    CAEDRNativeCreateDeviceSocketList();
+    ca_mutex_unlock(g_mutexObjectList);
+
+    if (isAttached)
+    {
         (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
 
-    CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)
-                                               OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));
+    CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) OICMalloc(
+            sizeof(CAAdapterReceiveThreadContext_t));
     if (!ctx)
     {
         OIC_LOG(ERROR, TAG, "Out of memory!");
-        return;
+        return CA_MEMORY_ALLOC_FAILED;
     }
 
     ctx->stopFlag = &g_stopAccept;
-    if (CA_STATUS_OK != u_thread_pool_add_task(g_threadPoolHandle, CAAcceptHandler, (void *)ctx))
+    if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, CAAcceptHandler, (void *) ctx))
     {
         OIC_LOG(ERROR, TAG, "Failed to create read thread!");
-        OICFree((void *)ctx);
-        return;
+        OICFree((void *) ctx);
+        return CA_STATUS_FAILED;
     }
 
-    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
 }
 
 void CAEDRServerTerminate()
@@ -396,300 +476,366 @@ void CAEDRServerTerminate()
     {
         return;
     }
-    jboolean isAttached = JNI_FALSE;
+    bool isAttached = false;
     JNIEnv* env;
-    jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6);
-    if(res != JNI_OK)
+    jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
+    if (JNI_OK != res)
     {
-        OIC_LOG_V(DEBUG, TAG, "CAEDRServerTerminate - Could not get JNIEnv pointer");
+        OIC_LOG(DEBUG, TAG, "Could not get JNIEnv pointer");
         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
 
-        if(res != JNI_OK)
+        if (JNI_OK != res)
         {
-            OIC_LOG_V(DEBUG, TAG, "AttachCurrentThread failed");
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
             return;
         }
-        isAttached = JNI_TRUE;
+        isAttached = true;
     }
 
+    CAEDRNativeSocketCloseToAll(env);
+
     if (isAttached)
     {
         (*g_jvm)->DetachCurrentThread(g_jvm);
     }
 
-    CAEDRServerNativeRemoveAllDeviceState();
-    CAEDRServerNativeRemoveAllDeviceSocket(env);
+    CAEDRNativeRemoveAllDeviceState();
+    CAEDRNativeRemoveAllDeviceSocket(env);
 
     // delete mutex
     CAEDRServerDestroyMutex();
 }
 
-int32_t CAEDRStartUnicastServer(const char* address, bool isSecured)
+CAResult_t CAEDRStartReceiveThread(bool isSecured)
 {
-    OIC_LOG_V(DEBUG, TAG, "CAEDRStartUnicastServer(%s)", address);
+    OIC_LOG(DEBUG, TAG, "CAEDRStartReceiveThread");
 
-    u_mutex_lock(g_mutexUnicastServer);
+    ca_mutex_lock(g_mutexReceiveServer);
 
     /**
-      * The task to listen for data from unicast is added to the thread pool.
-      * This is a blocking call is made where we try to receive some data..
-      * We will keep waiting until some data is received.
-      * This task will be terminated when thread pool is freed on stopping the adapters.
-      * Thread context will be freed by thread on exit.
-      */
-    CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)
-                                           OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));
+     * The task to listen for data from unicast is added to the thread pool.
+     * This is a blocking call is made where we try to receive some data..
+     * We will keep waiting until some data is received.
+     * This task will be terminated when thread pool is freed on stopping the adapters.
+     * Thread context will be freed by thread on exit.
+     */
+    CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) OICMalloc(
+            sizeof(CAAdapterReceiveThreadContext_t));
     if (!ctx)
     {
         OIC_LOG(ERROR, TAG, "Out of memory!");
-        u_mutex_unlock(g_mutexUnicastServer);
+        ca_mutex_unlock(g_mutexReceiveServer);
         return CA_MEMORY_ALLOC_FAILED;
     }
 
+    g_stopUnicast = false;
     ctx->stopFlag = &g_stopUnicast;
     ctx->type = isSecured ? CA_SECURED_UNICAST_SERVER : CA_UNICAST_SERVER;
-    if (CA_STATUS_OK != u_thread_pool_add_task(g_threadPoolHandle, CAReceiveHandler, (void *)ctx))
+    if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, CAReceiveHandler, (void *) ctx))
     {
         OIC_LOG(ERROR, TAG, "Failed to create read thread!");
-        u_mutex_unlock(g_mutexUnicastServer);
-        OICFree((void *)ctx);
+        ca_mutex_unlock(g_mutexReceiveServer);
+        OICFree((void *) ctx);
         return CA_STATUS_FAILED;
     }
-    u_mutex_unlock(g_mutexUnicastServer);
+    ca_mutex_unlock(g_mutexReceiveServer);
 
     OIC_LOG(DEBUG, TAG, "OUT");
     return CA_STATUS_OK;
 }
 
-int32_t CAEDRStartMulticastServer(bool isSecured)
+CAResult_t CAEDRStopReceiveThread()
 {
-    OIC_LOG_V(DEBUG, TAG, "CAEDRStartMulticastServer");
+    OIC_LOG(DEBUG, TAG, "CAEDRStopReceiveThread");
 
-    u_mutex_lock(g_mutexMulticastServer);
+    ca_mutex_lock(g_mutexReceiveServer);
+    g_stopUnicast = true;
+    ca_mutex_unlock(g_mutexReceiveServer);
 
-    /**
-      * The task to listen to data from multicast socket is added to the thread pool.
-      * This is a blocking call is made where we try to receive some data.
-      * We will keep waiting until some data is received.
-      * This task will be terminated when thread pool is freed on stopping the adapters.
-      * Thread context will be freed by thread on exit.
-      */
-    CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)
-                                           OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));
-    if (!ctx)
-    {
-        OIC_LOG(ERROR, TAG, "Out of memory!");
-        u_mutex_unlock(g_mutexMulticastServer);
+    return CA_STATUS_OK;
+}
 
-        return CA_MEMORY_ALLOC_FAILED;
+CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t idx)
+{
+    if ((*env)->ExceptionCheck(env))
+    {
+        (*env)->ExceptionDescribe(env);
+        (*env)->ExceptionClear(env);
+        OIC_LOG(ERROR, TAG, "env error!!");
+        return CA_STATUS_FAILED;
     }
 
-    ctx->stopFlag = &g_stopMulticast;
-    ctx->type = CA_MULTICAST_SERVER;
-
-    g_stopMulticast = false;
-    if (CA_STATUS_OK != u_thread_pool_add_task(g_threadPoolHandle, CAReceiveHandler, (void *)ctx))
+    jobject jni_obj_inputStream = CAEDRNativeGetInputStream(idx);
+    if (!jni_obj_inputStream)
     {
-        OIC_LOG(ERROR, TAG, "thread_pool_add_task failed!");
-
-        g_stopMulticast = true;
-        u_mutex_unlock(g_mutexMulticastServer);
-        OICFree((void *)ctx);
-
+        OIC_LOG(ERROR, TAG, "jni_obj_inputStream is null");
         return CA_STATUS_FAILED;
     }
-    u_mutex_unlock(g_mutexMulticastServer);
-
-    OIC_LOG(DEBUG, TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-int32_t CAEDRStopUnicastServer(int32_t serverID)
-{
-    OIC_LOG(DEBUG, TAG, "CAEDRStopUnicastServer");
-
-    u_mutex_lock(g_mutexUnicastServer);
-    g_stopUnicast = true;
-    u_mutex_unlock(g_mutexUnicastServer);
-
-    return 0;
-}
-
-int32_t CAEDRStopMulticastServer(int32_t serverID)
-{
-    OIC_LOG(DEBUG, TAG, "CAEDRStopMulticastServer");
-
-    u_mutex_lock(g_mutexMulticastServer);
-    g_stopMulticast = true;
-    u_mutex_unlock(g_mutexMulticastServer);
 
-    OIC_LOG_V(INFO, TAG, "Multicast server stopped");
+    jmethodID jni_mid_available = CAGetJNIMethodID(env, "java/io/InputStream", "available", "()I");
+    if (!jni_mid_available)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_available is null");
+        return CA_STATUS_FAILED;
+    }
 
-    return 0;
-}
+    jint available = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_available);
 
-CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id, CAAdapterServerType_t type)
-{
-    if(!((*env)->ExceptionCheck(env)))
+    if (0 < available)
     {
-        // check whether this socket object is connected or not.
-        jobject jni_obj_socket = CAEDRServerNativeGetDeviceSocket(id);
-        if(!jni_obj_socket)
+        jobject jni_obj_socket = CAEDRNativeGetDeviceSocket(idx);
+        if (!jni_obj_socket)
         {
-            return CA_STATUS_INVALID_PARAM;
+            OIC_LOG(ERROR, TAG, "jni_obj_socket is null");
+            return CA_STATUS_FAILED;
         }
 
         jstring jni_str_address = CAEDRNativeGetAddressFromDeviceSocket(env, jni_obj_socket);
+        if (!jni_str_address)
+        {
+            OIC_LOG(ERROR, TAG, "jni_str_address is null");
+            return CA_STATUS_FAILED;
+        }
+
         const char* address = (*env)->GetStringUTFChars(env, jni_str_address, NULL);
-        if(STATE_DISCONNECTED == CAEDRServerIsConnectedDevice(address))
+        if (!address)
         {
-            OIC_LOG(DEBUG, TAG, "[EDR][Native] btReadData: it is not connected yet..");
+            OIC_LOG(ERROR, TAG, "address is null");
+            (*env)->DeleteLocalRef(env, jni_str_address);
             return CA_STATUS_FAILED;
         }
 
-        // start to read through InputStream
-        jclass jni_cid_BTsocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
-        jmethodID jni_mid_getInputStream = (*env)->GetMethodID(env,
-                jni_cid_BTsocket, "getInputStream", "()Ljava/io/InputStream;");
-        OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btReadData:  get InputStream..%d, %s", id, address);
+        CAConnectedDeviceInfo_t *deviceInfo =
+                (CAConnectedDeviceInfo_t *) CAEDRGetDeviceInfoFromAddress(address);
+        if (!deviceInfo)
+        {
+            OIC_LOG(ERROR, TAG, "failed to get device info from list");
+            (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+            (*env)->DeleteLocalRef(env, jni_str_address);
+            return CA_STATUS_FAILED;
+        }
 
-        if(!jni_obj_socket)
+        jint bufSize = (deviceInfo->totalDataLen == 0) ? EDR_MAX_HEADER_LEN
+                                                       : deviceInfo->totalDataLen;
+        if (!deviceInfo->recvData)
         {
-            OIC_LOG(ERROR, TAG, "[EDR][Native] jni_obj_socket is not available anymore..");
+            deviceInfo->recvData = OICCalloc(1, bufSize);
+            if (!deviceInfo->recvData)
+            {
+                OIC_LOG(ERROR, TAG, "out of memory");
+                (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+                (*env)->DeleteLocalRef(env, jni_str_address);
+                return CA_STATUS_FAILED;
+            }
+        }
+
+        jint remainSize = (jint) bufSize - deviceInfo->recvDataLen;
+        if (0 >= remainSize)
+        {
+            OIC_LOG(ERROR, TAG, "remainSize value is invalid.");
+            (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+            (*env)->DeleteLocalRef(env, jni_str_address);
             return CA_STATUS_FAILED;
         }
 
-        jobject jni_obj_inputStream = (*env)->CallObjectMethod(env,
-                jni_obj_socket, jni_mid_getInputStream);
-        OIC_LOG(DEBUG, TAG, "[EDR][Native] btReadData:  ready inputStream..");
+        jbyteArray jbuf = (*env)->NewByteArray(env, remainSize);
+        if (!jbuf)
+        {
+            OIC_LOG(ERROR, TAG, "jbuf is null");
+            (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+            (*env)->DeleteLocalRef(env, jni_str_address);
+            return CA_STATUS_FAILED;
+        }
 
-        jclass jni_cid_InputStream = (*env)->FindClass(env, "java/io/InputStream");
-        jmethodID jni_mid_read = (*env)->GetMethodID(env, jni_cid_InputStream, "read", "([BII)I");
+        jmethodID jni_mid_read = CAGetJNIMethodID(env, "java/io/InputStream", "read", "([BII)I");
+        if (!jni_mid_read)
+        {
+            OIC_LOG(ERROR, TAG, "jni_mid_read is null");
+            (*env)->DeleteLocalRef(env, jbuf);
+            (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+            (*env)->DeleteLocalRef(env, jni_str_address);
+            return CA_STATUS_FAILED;
+        }
 
-        jbyteArray jbuf = (*env)->NewByteArray(env, MAX_PDU_BUFFER);
-        jlong nread;
+        OIC_LOG_V(DEBUG, TAG, "read InputStream (idx:%d, addr:%s)", idx, address);
+        jint recvLen = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_read,
+                                             jbuf, (jint) 0, remainSize);
+        if (-1 == recvLen)
+        {
+            OIC_LOG(ERROR, TAG, "recvLen is -1");
+            (*env)->DeleteLocalRef(env, jbuf);
+            (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+            (*env)->DeleteLocalRef(env, jni_str_address);
+            return CA_STATUS_FAILED;
+        }
+        OIC_LOG_V(DEBUG, TAG, "read success (length: %d bytes)", recvLen);
 
-        if(!jni_obj_socket)
+        jbyte* buf = (*env)->GetByteArrayElements(env, jbuf, NULL);
+        if (!buf)
         {
-            OIC_LOG(ERROR, TAG, "[EDR][Native] jni_obj_socket is not available anymore...");
+            OIC_LOG(ERROR, TAG, "buf is null");
+            (*env)->DeleteLocalRef(env, jbuf);
+            (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+            (*env)->DeleteLocalRef(env, jni_str_address);
             return CA_STATUS_FAILED;
         }
+        memcpy(deviceInfo->recvData + deviceInfo->recvDataLen, (const char*) buf, recvLen);
+        deviceInfo->recvDataLen += recvLen;
+
+        (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
+        (*env)->DeleteLocalRef(env, jbuf);
 
-        while ((nread = (*env)->CallIntMethod(env, jni_obj_inputStream,
-            jni_mid_read, jbuf, (jint)0, MAX_PDU_BUFFER)) != -1)
+        if (!deviceInfo->totalDataLen)
         {
-            if((*env)->ExceptionCheck(env))
+            coap_transport_type transport = coap_get_tcp_header_type_from_initbyte(
+                    ((unsigned char *) deviceInfo->recvData)[0] >> 4);
+            size_t headerLen = coap_get_tcp_header_length_for_transport(transport);
+            if (deviceInfo->recvData && deviceInfo->recvDataLen >= headerLen)
             {
-                OIC_LOG(ERROR, TAG, "[EDR][Native] btReadData: read Error!!!");
-                (*env)->ExceptionDescribe(env);
-                (*env)->ExceptionClear(env);
-                return CA_STATUS_FAILED;
+                deviceInfo->totalDataLen = coap_get_total_message_length(deviceInfo->recvData,
+                                                                         deviceInfo->recvDataLen);
+                OIC_LOG_V(DEBUG, TAG, "total data length [%d] bytes", deviceInfo->totalDataLen);
+
+                uint8_t *newBuf = OICRealloc(deviceInfo->recvData, deviceInfo->totalDataLen);
+                if (!newBuf)
+                {
+                    OIC_LOG(ERROR, TAG, "out of memory");
+                    (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+                    (*env)->DeleteLocalRef(env, jni_str_address);
+                    return CA_STATUS_FAILED;
+                }
+                deviceInfo->recvData = newBuf;
             }
-            OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btReadData: reading");
-            jbyte* buf = (*env)->GetByteArrayElements(env, jbuf, NULL);
-            jint length = strlen((char*)buf);
-            OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btReadData: read %s", buf);
-            if (buf == NULL)
+        }
+
+        if (deviceInfo->totalDataLen == deviceInfo->recvDataLen)
+        {
+            if ((*env)->ExceptionCheck(env))
             {
+                OIC_LOG(ERROR, TAG, "read Error!!!");
+                (*env)->ExceptionDescribe(env);
+                (*env)->ExceptionClear(env);
+
+                // update state to disconnect
+                // the socket will be close next read thread routine
+                ca_mutex_lock(g_mutexStateList);
+                CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
+                ca_mutex_unlock(g_mutexStateList);
+
+                (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+                (*env)->DeleteLocalRef(env, jni_str_address);
                 return CA_STATUS_FAILED;
             }
 
-            switch (type)
+            if (g_edrPacketReceivedCallback)
             {
-                case CA_UNICAST_SERVER:
-                case CA_MULTICAST_SERVER:
-                    // Notify data to upper layer
-                    if (g_EDRPacketReceivedCallback)
-                    {
-                        uint32_t sentLength = 0;
-                        OIC_LOG_V(DEBUG, TAG, "[EDR][Native] data will be sent \
-                                to callback routine: %s, %d", buf, length);
-                        g_EDRPacketReceivedCallback(address, (void*)buf, length, &sentLength);
-                    }
-                    break;
-
-                default:
-                    // Should never occur
-                    OIC_LOG_V(DEBUG, TAG, "Invalid server type");
-                    return CA_STATUS_FAILED;
-            }
-            (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
+                OIC_LOG_V(DEBUG, TAG, "data will be sent to callback routine: %s, %d",
+                          deviceInfo->recvData, deviceInfo->recvDataLen);
 
-            // close socket after data was sent
-            CAEDRNativeServerSocketClose(env, address, id);
-            break;
+                uint32_t sentLength = 0;
+                g_edrPacketReceivedCallback(address, (void*) deviceInfo->recvData,
+                                            deviceInfo->recvDataLen, &sentLength);
+
+                OICFree(deviceInfo->recvData);
+                deviceInfo->recvData = NULL;
+                deviceInfo->recvDataLen = 0;
+                deviceInfo->totalDataLen = 0;
+            }
         }
+
+        (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+        (*env)->DeleteLocalRef(env, jni_str_address);
     }
-    else
+
+    return CA_STATUS_OK;
+}
+
+void CANativeStartListenTask(JNIEnv *env)
+{
+    jobject jni_obj_BTServerSocket = CAEDRNativeListen(env);
+    if (!jni_obj_BTServerSocket)
     {
-        (*env)->ExceptionDescribe(env);
-        (*env)->ExceptionClear(env);
-        OIC_LOG(DEBUG, TAG, "[EDR][Native] btReadData: env error!!");
-        return CA_STATUS_FAILED;
+        OIC_LOG(ERROR, TAG, "jni_obj_BTServerSocket is null");
+        return;
     }
 
-    return CA_STATUS_OK;
+    ca_mutex_lock(g_mutexServerSocket);
+    g_serverSocket = (*env)->NewGlobalRef(env, jni_obj_BTServerSocket);
+    ca_mutex_unlock(g_mutexServerSocket);
 }
 
 jobject CAEDRNativeListen(JNIEnv *env)
 {
-    OIC_LOG(DEBUG, TAG, "[EDR][Native] btListen");
+    OIC_LOG(DEBUG, TAG, "CAEDRNativeListen - IN");
+
+    if (!CAEDRNativeIsEnableBTAdapter(env))
+    {
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return NULL;
+    }
 
-    jclass jni_cid_BTAdapter = (*env)->FindClass(env,  CLASSPATH_BT_ADPATER);
-    if(!jni_cid_BTAdapter)
+    jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
+    if (!jni_cid_BTAdapter)
     {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_cid_BTAdapter is null");
+        OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
         return NULL;
     }
 
     // get BTadpater
-    jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env,
-            jni_cid_BTAdapter, "getDefaultAdapter", METHODID_OBJECTNONPARAM);
-    if(!jni_cid_BTAdapter)
+    jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
+                                                                    "getDefaultAdapter",
+                                                                    METHODID_OBJECTNONPARAM);
+    if (!jni_mid_getDefaultAdapter)
     {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_cid_BTAdapter is null");
+        OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
         return NULL;
     }
 
-    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(ERROR, TAG, "[EDR][Native] btListen: jni_obj_BTAdapter is null");
+        OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
         return NULL;
     }
 
     // get listen method ID
-    jmethodID jni_mid_listen = (*env)->GetMethodID(env, jni_cid_BTAdapter,
-                  "listenUsingInsecureRfcommWithServiceRecord",
-                  "(Ljava/lang/String;Ljava/util/UUID;)Landroid/bluetooth/BluetoothServerSocket;");
-    if(!jni_mid_listen)
+    jmethodID jni_mid_listen = (*env)->GetMethodID(
+            env, jni_cid_BTAdapter, "listenUsingInsecureRfcommWithServiceRecord",
+            "(Ljava/lang/String;Ljava/util/UUID;)Landroid/bluetooth/BluetoothServerSocket;");
+    if (!jni_mid_listen)
     {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_mid_listen is null");
+        OIC_LOG(ERROR, TAG, "jni_mid_listen is null");
         return NULL;
     }
     // listenUsingInsecureRfcommWithServiceRecord  / listenUsingRfcommWithServiceRecord
     // setting UUID
     jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
-    if(!jni_cid_uuid)
+    if (!jni_cid_uuid)
     {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_mid_listen is null");
+        OIC_LOG(ERROR, TAG, "jni_mid_listen is null");
         return NULL;
     }
 
-    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(ERROR, TAG, "[EDR][Native] btListen: jni_mid_fromString is null");
+        OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
         return NULL;
     }
 
-    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(ERROR, TAG, "[EDR][Native] btListen: jni_obj_uuid is null");
+        OIC_LOG(ERROR, TAG, "jni_uuid is null");
+        return NULL;
+    }
+    jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
+                                                          jni_uuid);
+    if (!jni_obj_uuid)
+    {
+        OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
         return NULL;
     }
 
@@ -697,565 +843,119 @@ jobject CAEDRNativeListen(JNIEnv *env)
     jstring jni_name = (*env)->NewStringUTF(env, "BluetoothTestSecure");
     if (!jni_name)
     {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_name is null");
+        OIC_LOG(ERROR, TAG, "jni_name is null");
         return NULL;
     }
-    jobject jni_obj_BTSeverSocket = (*env)->CallObjectMethod(env,
-            jni_obj_BTAdapter, jni_mid_listen, jni_name, jni_obj_uuid);
-    if(!jni_obj_BTSeverSocket)
+    jobject jni_obj_BTServerSocket = (*env)->CallObjectMethod(env, jni_obj_BTAdapter, jni_mid_listen,
+                                                             jni_name, jni_obj_uuid);
+    if (!jni_obj_BTServerSocket)
     {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_obj_BTSeverSocket is null");
+        OIC_LOG(ERROR, TAG, "jni_obj_BTServerSocket is null");
         return NULL;
     }
 
-    g_serverSocketObject = (*env)->NewGlobalRef(env, jni_obj_BTSeverSocket);
+    OIC_LOG(DEBUG, TAG, "CAEDRNativeListen - OUT");
 
-    return jni_obj_BTSeverSocket;
+    return jni_obj_BTServerSocket;
 }
 
-void CAEDRNativeAccept(JNIEnv *env, jobject severSocketObject)
+void CAEDRNativeAccept(JNIEnv *env, jobject serverSocketObject)
 {
-    if(severSocketObject != NULL)
-    {
-        jclass jni_cid_BTServerSocket = (*env)->FindClass(env,
-                "android/bluetooth/BluetoothServerSocket");
-        if(!jni_cid_BTServerSocket)
-        {
-            OIC_LOG(ERROR, TAG, "[EDR][Native] btAccept: jni_cid_BTServerSocket is null");
-            return;
-        }
+    OIC_LOG(DEBUG, TAG, "CAEDRNativeAccept - IN");
 
-        jmethodID jni_mid_accept = (*env)->GetMethodID(env,
-                jni_cid_BTServerSocket, "accept",
-                "(I)Landroid/bluetooth/BluetoothSocket;");
-        if(!jni_mid_accept)
+    if (NULL != serverSocketObject)
+    {
+        jmethodID jni_mid_accept = CAGetJNIMethodID(env, CLASSPATH_BT_SERVER_SOCKET,
+                                                    "accept",
+                                                    "()Landroid/bluetooth/BluetoothSocket;");
+        if (!jni_mid_accept)
         {
-            OIC_LOG(ERROR, TAG, "[EDR][Native] btAccept: jni_mid_accept is null");
+            OIC_LOG(ERROR, TAG, "jni_mid_accept is null");
             return;
         }
 
-        OIC_LOG(DEBUG, TAG, "[EDR][Native] btAccept: initiating accept...");
+        OIC_LOG(DEBUG, TAG, "waiting for the new connection request...");
 
-        jobject jni_obj_BTSocket = NULL;
-        jni_obj_BTSocket = (*env)->CallObjectMethod(env, severSocketObject, jni_mid_accept, 1000);
-        if(!jni_obj_BTSocket)
+        jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, serverSocketObject,
+                                                            jni_mid_accept);
+        if (!jni_obj_BTSocket)
         {
-            OIC_LOG(ERROR, TAG, "[EDR][Native] btAccept: jni_obj_BTSocket is null");
-            return;
+            OIC_LOG(ERROR, TAG, "jni_obj_BTSocket is null");
+
+            if ((*env)->ExceptionCheck(env))
+            {
+                OIC_LOG(ERROR, TAG, "socket might closed or timeout!!!");
+                (*env)->ExceptionDescribe(env);
+                (*env)->ExceptionClear(env);
+                return;
+            }
         }
 
         // get remote address
         jstring j_str_address = CAEDRNativeGetAddressFromDeviceSocket(env, jni_obj_BTSocket);
-
-        const char* address = (*env)->GetStringUTFChars(env, j_str_address, NULL);
-        OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btAccept: address is %s", address);
-
-        // set socket to list
-        jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
-        CAEDRServerNativeAddDeviceSocketToList(env, jni_socket);
-
-        OIC_LOG(DEBUG, TAG, "[EDR][Native] btAccept: Accepted!!");
-
-        // update state
-        CAEDRServerUpdateDeviceState(STATE_CONNECTED, address);
-        (*env)->ReleaseStringUTFChars(env, j_str_address, address);
-    }
-    else
-    {
-        OIC_LOG(DEBUG, TAG, "[EDR][Native] btAccept: severSocket is close previously");
-    }
-}
-
-void CAEDRNativeServerSocketClose(JNIEnv *env, const char *address, uint32_t id)
-{
-
-    jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
-    if(!jni_cid_BTSocket)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] close: jni_cid_BTSocket is null");
-        return;
-    }
-
-    jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_BTSocket, "close", "()V");
-    if(!jni_mid_close)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] close: jni_mid_close is null");
-        return;
-    }
-
-    jobject jni_obj_socket = CAEDRServerNativeGetDeviceSocket(id);
-    if(!jni_obj_socket)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] close: jni_obj_socket is not available");
-        return;
-    }
-
-    (*env)->CallVoidMethod(env, jni_obj_socket, jni_mid_close);
-
-    if((*env)->ExceptionCheck(env))
-    {
-        OIC_LOG(DEBUG, TAG, "[EDR][Native] close: close is Failed!!!");
-        (*env)->ExceptionDescribe(env);
-        (*env)->ExceptionClear(env);
-        return;
-    }
-
-    // remove socket to list
-    CAEDRServerNativeRemoveDeviceSocket(env, jni_obj_socket);
-
-    // update state
-    CAEDRServerUpdateDeviceState(STATE_DISCONNECTED, address);
-
-    OIC_LOG(DEBUG, TAG, "[EDR][Native] close: disconnected");
-}
-
-/**
- * BT State List
- */
-void CAEDRServerNativeCreateDeviceStateList()
-{
-    OIC_LOG(DEBUG, TAG, "[EDR][Native] CAEDRNativeCreateDeviceStateList");
-
-    // create new object array
-    if (g_deviceStateList == NULL)
-    {
-        OIC_LOG_V(DEBUG, TAG, "Create device list");
-
-        g_deviceStateList = u_arraylist_create();
-        if (g_deviceStateList == NULL)
-        {
-            OIC_LOG_V(DEBUG, TAG, "Create device list is null");
-        }
-    }
-}
-
-void CAEDRServerUpdateDeviceState(uint32_t state, const char *address)
-{
-    state_t *newstate = (state_t*) OICCalloc(1, sizeof(state_t));
-    if (!newstate) {
-        OIC_LOG(ERROR, TAG, "[BLE][Native] newstate is null");
-        return;
-    }
-    strcpy(newstate->address, address);
-    newstate->state = state;
-
-    CAEDRServerNativeAddDeviceStateToList(newstate);
-}
-
-void CAEDRServerNativeAddDeviceStateToList(state_t *state)
-{
-    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(!CAEDRServerNativeIsDeviceInList(state->address)) {
-        CAEDRServerNativeRemoveDevice(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 to Connected State List");
-    }
-}
-
-jboolean CAEDRServerNativeIsDeviceInList(const char* remoteAddress){
-
-    if (!remoteAddress) {
-        OIC_LOG(ERROR, TAG, "[BLE][Native] remoteAddress is null");
-        return JNI_TRUE;
-    }
-    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(ERROR, TAG, "[EDR][Native] state_t object is null");
-            return JNI_TRUE;
-        }
-
-        if(!strcmp(remoteAddress, state->address))
-        {
-            OIC_LOG_V(DEBUG, TAG, "the device is already set");
-            return JNI_TRUE;
-        }
-        else
+        if (!j_str_address)
         {
-            continue;
-        }
-    }
-
-    OIC_LOG_V(DEBUG, TAG, "there are no the device in list.");
-    return JNI_FALSE;
-}
-
-void CAEDRServerNativeRemoveAllDeviceState()
-{
-    OIC_LOG_V(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 CAEDRServerNativeRemoveDevice(const char *remoteAddress)
-{
-    OIC_LOG_V(DEBUG, TAG, "CAEDRNativeRemoveDevice");
-
-    if(!g_deviceStateList)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceStateList is null");
-        return;
-    }
-    if (!remoteAddress) {
-        OIC_LOG(ERROR, TAG, "[BLE][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;
+            OIC_LOG(ERROR, TAG, "j_str_address is null");
+            return;
         }
 
-        if(!strcmp(state->address, remoteAddress))
-        {
-            OIC_LOG_V(DEBUG, TAG, "[EDR][Native] remove object : %s", remoteAddress);
-            OICFree(state);
+        const char* address = (*env)->GetStringUTFChars(env, j_str_address, NULL);
 
-            CAEDRServerReorderingDeviceList(index);
-            break;
-        }
-    }
-    OIC_LOG(DEBUG, TAG, "[EDR][Native] there are no target object");
-    return;
-}
+        OIC_LOG_V(INFO, TAG, "accept a new connection from [%s]", address);
 
-jboolean CAEDRServerIsConnectedDevice(const char *remoteAddress)
-{
-    OIC_LOG_V(DEBUG, TAG, "CAEDRServerIsConnectedDevice");
+        // update state
+        ca_mutex_lock(g_mutexStateList);
+        CAEDRUpdateDeviceState(STATE_CONNECTED, address);
+        ca_mutex_unlock(g_mutexStateList);
 
-    if(!g_deviceStateList)
-    {
-        OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceStateList is null");
-        return JNI_FALSE;
-    }
-    if (!remoteAddress) {
-        OIC_LOG(ERROR, TAG, "[BLE][Native] remoteAddress is null");
-        return JNI_FALSE;
-    }
+        (*env)->ReleaseStringUTFChars(env, j_str_address, address);
+        (*env)->DeleteLocalRef(env, j_str_address);
 
-    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)
+        // set socket to list
+        jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
+        if (!jni_socket)
         {
-            OIC_LOG(DEBUG, TAG, "[EDR][Native] state_t object is null");
-            continue;
+            OIC_LOG(ERROR, TAG, "jni_socket is null");
+            (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
+            return;
         }
 
-        if(!strcmp(state->address, remoteAddress))
-        {
-            OIC_LOG_V(DEBUG, TAG, "[EDR][Native] check whether it is connected or not");
-
-            return state->state;
-        }
-    }
-    OIC_LOG(DEBUG, TAG, "[EDR][Native] there are no target object");
-    return JNI_FALSE;
-}
+        ca_mutex_lock(g_mutexObjectList);
+        CAEDRNativeAddDeviceSocketToList(env, jni_socket);
+        ca_mutex_unlock(g_mutexObjectList);
 
-void CAEDRServerReorderingDeviceList(uint32_t index)
-{
-    if (index >= g_deviceStateList->length)
-    {
-        return;
+        (*env)->DeleteGlobalRef(env, jni_socket);
+        (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
     }
-
-    if (index < g_deviceStateList->length - 1)
+    else
     {
-        memmove(&g_deviceStateList->data[index], &g_deviceStateList->data[index + 1],
-                (g_deviceStateList->length - index - 1) * sizeof(void *));
+        OIC_LOG(DEBUG, TAG, "serverSocket is close previously");
     }
 
-    g_deviceStateList->size--;
-    g_deviceStateList->length--;
+    OIC_LOG(DEBUG, TAG, "CAEDRNativeAccept - OUT");
 }
 
 /**
- * Device Socket Object List
+ * InputStream & BluetoothServerSocket will be close for Terminating.
  */
-void CAEDRServerNativeCreateDeviceSocketList()
+void CAEDRNatvieCloseServerTask(JNIEnv* env)
 {
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CAEDRServerNativeCreateDeviceSocketList");
-
-    // create new object array
-    if (g_deviceObjectList == NULL)
+    if (g_serverSocket)
     {
-        OIC_LOG_V(DEBUG, TAG, "Create Device object list");
+        OIC_LOG(DEBUG, TAG, "Accept Resource will be close");
 
-        g_deviceObjectList = u_arraylist_create();
-        if (g_deviceObjectList == NULL)
+        jmethodID jni_mid_close = CAGetJNIMethodID(env, CLASSPATH_BT_SERVER_SOCKET,
+                                                   "close", "()V");
+        if (!jni_mid_close)
         {
-            OIC_LOG_V(DEBUG, TAG, "Create Device object list is null");
-        }
-    }
-}
-
-void CAEDRServerNativeAddDeviceSocketToList(JNIEnv *env, jobject deviceSocket)
-{
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CAEDRServerNativeAddDeviceSocketToList");
-
-    if(!deviceSocket)
-    {
-        OIC_LOG(ERROR, TAG, "[BLE][Native] Device is null");
-        return;
-    }
-
-    if(!g_deviceObjectList)
-    {
-        OIC_LOG(ERROR, TAG, "[BLE][Native] gdeviceObjectList is null");
-        return;
-    }
-
-    jstring jni_remoteAddress = CAEDRNativeGetAddressFromDeviceSocket(env, deviceSocket);
-    if(!jni_remoteAddress)
-    {
-        OIC_LOG(ERROR, TAG, "[BLE][Native] jni_remoteAddress is null");
-        return;
-    }
-
-    u_mutex_lock(g_mutexSocketListManager);
-
-    const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
-
-    if(!CAEDRServerNativeIsDeviceSocketInList(env, remoteAddress))
-    {
-        jobject gDeviceSocket = (*env)->NewGlobalRef(env, deviceSocket);
-        u_arraylist_add(g_deviceObjectList, gDeviceSocket);
-        OIC_LOG_V(DEBUG, TAG, "Set Object to Array as Element");
-    }
-
-    (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
-    u_mutex_unlock(g_mutexSocketListManager);
-}
-
-jboolean CAEDRServerNativeIsDeviceSocketInList(JNIEnv *env, const char* remoteAddress)
-{
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeIsDeviceObjInList");
-
-    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(ERROR, TAG, "[BLE][Native] jarrayObj is null");
-            return JNI_TRUE;
-        }
-
-        jstring jni_setAddress = CAEDRNativeGetAddressFromDeviceSocket(env, jarrayObj);
-        if(!jni_setAddress)
-        {
-            OIC_LOG(ERROR, TAG, "[BLE][Native] jni_setAddress is null");
-            return JNI_TRUE;
-        }
-
-        const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
-        if (!setAddress || !remoteAddress) {
-            OIC_LOG(ERROR, TAG, "[BLE][Native] setAddress or remoteAddress is null");
-            return JNI_TRUE;
-        }
-        if(!strcmp(remoteAddress, setAddress))
-        {
-            OIC_LOG_V(DEBUG, TAG, "the device is already set");
-            return JNI_TRUE;
-        }
-        else
-        {
-            continue;
-        }
-    }
-
-    OIC_LOG_V(DEBUG, TAG, "there are no the Device obejct in list. we can add");
-    return JNI_FALSE;
-}
-
-void CAEDRServerNativeRemoveAllDeviceSocket(JNIEnv *env)
-{
-    OIC_LOG_V(DEBUG, TAG, "CANativeRemoveAllDeviceObjsList");
-
-    if(!g_deviceObjectList)
-    {
-        OIC_LOG(ERROR, TAG, "[BLE][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(ERROR, TAG, "[BLE][Native] jarrayObj is null");
+            OIC_LOG(ERROR, TAG, "jni_mid_close is null");
             return;
         }
-        (*env)->DeleteGlobalRef(env, jarrayObj);
-    }
 
-    OICFree(g_deviceObjectList);
-    g_deviceObjectList = NULL;
-    return;
-}
+        (*env)->CallVoidMethod(env, g_serverSocket, jni_mid_close);
+        (*env)->DeleteGlobalRef(env, g_serverSocket);
+        g_serverSocket = NULL;
 
-void CAEDRServerNativeRemoveDeviceSocket(JNIEnv *env, jobject deviceSocket)
-{
-    OIC_LOG_V(DEBUG, TAG, "CAEDRServerNativeRemoveDeviceSocket");
-
-    if(!g_deviceObjectList)
-    {
-        OIC_LOG(ERROR, TAG, "[BLE][Native] gdeviceObjectList is null");
-        return;
+        OIC_LOG(DEBUG, TAG, "close accept obj");
     }
-
-    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, "[BLE][Native] jarrayObj is null");
-            continue;
-        }
-
-        jstring jni_setAddress = CAEDRNativeGetAddressFromDeviceSocket(env, jarrayObj);
-        if(!jni_setAddress)
-        {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_setAddress is null");
-            continue;
-        }
-        const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
-        (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
-
-        jstring jni_remoteAddress = CAEDRNativeGetAddressFromDeviceSocket(env, deviceSocket);
-        if(!jni_remoteAddress)
-        {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_remoteAddress is null");
-            continue;
-        }
-        const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
-        (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
-
-        if (!setAddress || !remoteAddress) {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] setAddress or remoteAddress is null");
-            continue;
-        }
-        if(!strcmp(setAddress, remoteAddress))
-        {
-            OIC_LOG_V(DEBUG, TAG, "[BLE][Native] remove object : %s", remoteAddress);
-            (*env)->DeleteGlobalRef(env, jarrayObj);
-
-            CAEDRServerReorderingDeviceSocketList(index);
-            break;
-        }
-    }
-    u_mutex_unlock(g_mutexSocketListManager);
-
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] there are no target object");
-    return;
-}
-
-jobject CAEDRServerNativeGetDeviceSocket(uint32_t idx)
-{
-    OIC_LOG_V(DEBUG, TAG, "CAEDRServerNativeGetDeviceSocket");
-
-    if(idx < 0)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] index is not available");
-        return NULL;
-    }
-
-    if(!g_deviceObjectList)
-    {
-        OIC_LOG(ERROR, TAG, "[BLE][Native] gdeviceObjectList is null");
-        return NULL;
-    }
-
-    jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, idx);
-    if(!jarrayObj)
-    {
-        OIC_LOG(ERROR, TAG, "[BLE][Native] jarrayObj is not available");
-        return NULL;
-    }
-    return jarrayObj;
 }
-
-uint32_t CAEDRServerGetSocketListLength()
-{
-    if(!g_deviceObjectList)
-    {
-        OIC_LOG(ERROR, TAG, "[BLE][Native] gdeviceObjectList is null");
-        return 0;
-    }
-
-    uint32_t length = u_arraylist_length(g_deviceObjectList);
-
-    return length;
-}
-
-void CAEDRServerReorderingDeviceSocketList(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 CAEDRServerSetPacketReceivedCallback
-    (CAEDRDataReceivedCallback packetReceivedCallback)
-{
-    g_EDRPacketReceivedCallback = packetReceivedCallback;
-}
-
-
-