check if send request is sucessful or not.
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / android / caleclient.c
index d5fc698..8e7502f 100644 (file)
+/******************************************************************
+ *
+ * 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 <jni.h>
+#include <unistd.h>
 
-#include "calecore.h"
+#include "caleclient.h"
 #include "caleserver.h"
+#include "caleutils.h"
+#include "caleinterface.h"
+#include "caadapterutils.h"
+
 #include "logger.h"
 #include "oic_malloc.h"
-#include "uthreadpool.h" /* for thread pool */
-#include "umutex.h"
+#include "oic_string.h"
+#include "cathreadpool.h" /* for thread pool */
+#include "camutex.h"
 #include "uarraylist.h"
-#include "com_iotivity_jar_CALeInterface.h"
-
-//#define DEBUG_MODE
-#define TAG PCF("CA")
-
-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_GATT = "android/bluetooth/BluetoothGatt";
-
-static const char *IOTIVITY_GATT_SERVIE_UUID = "713d0000-503e-4c75-ba94-3148f18d941e";
-static const char *IOTIVITY_GATT_TX_UUID = "713d0003-503e-4c75-ba94-3148f18d941e";
-static const char *IOTIVITY_GATT_RX_UUID = "713d0002-503e-4c75-ba94-3148f18d941e";
-
-static const uint32_t STATE_CONNECTED = 2;
-static const uint32_t STATE_DISCONNECTED = 0;
-static const uint32_t GATT_SUCCESS = 0;
-
-static JavaVM *g_jvm;
-static u_arraylist_t *gdeviceList = NULL;
-static u_arraylist_t *gGattObjectList = NULL;
-static CAPacketReceiveCallback gPacketReceiveCallback = NULL;
-static u_thread_pool_t gThreadPoolHandle = NULL;
-static jobject gLeScanCallback;
-static jobject gLeGattCallback;
-static jobject gContext;
-static jobjectArray gUUIDList;
-static jboolean gIsStartServer;
-static jboolean gIsFinishSendData;
-
-static jbyteArray gSendBuffer;
-static uint32_t gTargetCnt = 0;
-static uint32_t gCurrentSentCnt = 0;
-
-/** mutex for synchrnoization **/
-static u_mutex gThreadMutex;
-/** conditional mutex for synchrnoization **/
-static u_cond gThreadCond;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//FIXME getting context
-void CALEClientJNISetContext(JNIEnv *env, jobject context)
-{
-    OIC_LOG_V(DEBUG, TAG, "CALEClientJNISetContext");
-
-    if(context == NULL)
-    {
-        OIC_LOG_V(DEBUG, TAG, "context is null");
-        return;
-    }
+#include "org_iotivity_ca_CaLeClientInterface.h"
+
+#define TAG PCF("OIC_CA_LE_CLIENT")
+
+#define MICROSECS_PER_SEC 1000000
+#define WAIT_TIME_WRITE_CHARACTERISTIC 10 * MICROSECS_PER_SEC
+
+static ca_thread_pool_t g_threadPoolHandle = NULL;
+
+JavaVM *g_jvm;
+static u_arraylist_t *g_deviceList = NULL; // device list to have same UUID
+static u_arraylist_t *g_gattObjectList = NULL;
+static u_arraylist_t *g_deviceStateList = NULL;
+
+static CAPacketReceiveCallback g_packetReceiveCallback = NULL;
+static CABLEErrorHandleCallback g_clientErrorCallback;
+static jobject g_leScanCallback = NULL;
+static jobject g_leGattCallback = NULL;
+static jobject g_context = NULL;
+static jobjectArray g_uuidList = NULL;
+
+// it will be prevent to start send logic when adapter has stopped.
+static bool g_isStartedLEClient = false;
+static bool g_isStartedMulticastServer = false;
+static bool g_isStartedScan = false;
+
+static jbyteArray g_sendBuffer = NULL;
+static uint32_t g_targetCnt = 0;
+static uint32_t g_currentSentCnt = 0;
+static bool g_isFinishedSendData = false;
+static ca_mutex g_SendFinishMutex = NULL;
+static ca_mutex g_threadMutex = NULL;
+static ca_cond g_threadCond = NULL;
+static ca_cond g_deviceDescCond = NULL;
+
+static ca_mutex g_threadSendMutex = NULL;
+static ca_mutex g_threadWriteCharacteristicMutex = NULL;
+static ca_cond g_threadWriteCharacteristicCond = NULL;
+static bool g_isSignalSetFlag = false;
+
+static ca_mutex g_bleReqRespClientCbMutex = NULL;
+static ca_mutex g_bleServerBDAddressMutex = NULL;
+
+static ca_mutex g_deviceListMutex = NULL;
+static ca_mutex g_gattObjectMutex = NULL;
+static ca_mutex g_deviceStateListMutex = NULL;
+
+static ca_mutex g_scanMutex = NULL;
+
+static CABLEDataReceivedCallback g_CABLEClientDataReceivedCallback = NULL;
 
-    gContext = (*env)->NewGlobalRef(env, context);
+static jboolean g_autoConnectFlag = JNI_FALSE;
+
+//getting jvm
+void CALEClientJniInit()
+{
+    OIC_LOG(DEBUG, TAG, "CALEClientJniInit");
+    g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
+}
+
+void CALEClientJNISetContext()
+{
+    OIC_LOG(DEBUG, TAG, "CALEClientJNISetContext");
+    g_context = (jobject) CANativeJNIGetContext();
 }
 
-void CALeCreateJniInterfaceObject()
+CAResult_t CALECreateJniInterfaceObject()
 {
-    OIC_LOG_V(DEBUG, TAG, "CALeCreateJniInterfaceObject");
+    OIC_LOG(DEBUG, TAG, "CALECreateJniInterfaceObject");
+
+    if (!g_context)
+    {
+        OIC_LOG(ERROR, TAG, "g_context is null");
+        return CA_STATUS_FAILED;
+    }
 
-    jboolean isAttached = FALSE;
+    if (!g_jvm)
+    {
+        OIC_LOG(ERROR, TAG, "g_jvm is null");
+        return CA_STATUS_FAILED;
+    }
+
+    bool isAttached = false;
     JNIEnv* env;
-    jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6);
-    if(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, "Could not get JNIEnv pointer");
+        OIC_LOG(INFO, 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 has failed");
+            return CA_STATUS_FAILED;
         }
-        isAttached = TRUE;
+        isAttached = true;
     }
 
-    jclass LeJniInterface = (*env)->FindClass(env, "com/iotivity/jar/CALeInterface");
-    if (!LeJniInterface)
+    jclass jni_LEInterface = (*env)->FindClass(env, "org/iotivity/ca/CaLeClientInterface");
+    if (!jni_LEInterface)
     {
-        OIC_LOG_V(DEBUG, TAG, "Could not get CALeInterface class");
-        return;
+        OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface class");
+        goto error_exit;
     }
 
-    jmethodID LeInterfaceConstructorMethod =
-            (*env)->GetMethodID(env, LeJniInterface, "<init>", "(Landroid/content/Context;)V");
+    jmethodID LeInterfaceConstructorMethod = (*env)->GetMethodID(env, jni_LEInterface, "<init>",
+                                                                 "(Landroid/content/Context;)V");
     if (!LeInterfaceConstructorMethod)
     {
-        OIC_LOG_V(DEBUG, TAG, "Could not get CALeInterface constructor method");
-        return;
+        OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface constructor method");
+        goto error_exit;
     }
 
-    (*env)->NewObject(env, LeJniInterface, LeInterfaceConstructorMethod, gContext);
-    OIC_LOG_V(DEBUG, TAG, "Create CALeInterface instance");
-
-    if(isAttached)
-        (*g_jvm)->DetachCurrentThread(g_jvm);
-}
-
-JNIEXPORT jint JNI_OnLoad(JavaVM *jvm, void *reserved)
-{
-    OIC_LOG_V(DEBUG, TAG, "JNI_OnLoad in calecore");
+    (*env)->NewObject(env, jni_LEInterface, LeInterfaceConstructorMethod, g_context);
+    OIC_LOG(DEBUG, TAG, "Create instance for CaLeClientInterface");
 
-    JNIEnv* env;
-    if((*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_6) != JNI_OK)
+    if (isAttached)
     {
-        return -1;
+        (*g_jvm)->DetachCurrentThread(g_jvm);
     }
-    g_jvm = jvm;  /* cache the JavaVM pointer */
-
-    //JVM required for WifiCore to work with JNI interface
-    CAWiFiJniInit(jvm);
-    CALeServerJniInit(env, jvm);
 
-    return JNI_VERSION_1_6;
-}
+    return CA_STATUS_OK;
 
-void JNI_OnUnload(JavaVM *jvm, void *reserved)
-{
-    OIC_LOG_V(DEBUG, TAG, "JNI_OnUnload in calecore");
+error_exit:
 
-    JNIEnv* env;
-    if((*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_6) != JNI_OK)
+    if (isAttached)
     {
-        return;
+        (*g_jvm)->DetachCurrentThread(g_jvm);
     }
-    g_jvm = 0;
-    return;
-}
-
-JNIEXPORT void JNICALL Java_com_iotivity_jar_CALeInterface_CARegisterLeScanCallback(JNIEnv *env,
-        jobject obj, jobject callback)
-{
-    OIC_LOG_V(DEBUG, TAG, "CARegisterLeScanCallback");
 
-    gLeScanCallback = (*env)->NewGlobalRef(env, callback);
+    return CA_STATUS_FAILED;
 }
 
-JNIEXPORT void JNICALL Java_com_iotivity_jar_CALeInterface_CARegisterLeGattCallback(JNIEnv *env,
-        jobject obj, jobject callback)
+CAResult_t CALEClientInitialize()
 {
-    OIC_LOG_V(DEBUG, TAG, "CARegisterLeGattCallback");
+    OIC_LOG(DEBUG, TAG, "CALEClientInitialize");
 
-    gLeGattCallback = (*env)->NewGlobalRef(env, callback);
-}
-
-JNIEXPORT void JNICALL Java_com_iotivity_jar_CALeInterface_CALeScanCallback (JNIEnv *env,
-        jobject obj, jobject device, jint rssi, jbyteArray scanRecord)
-{
-    CANativeAddScanDeviceToList(env, device);
-}
-
-/*
- * Class:     com_iotivity_jar_CALeInterface
- * Method:    CALeGattConnectionStateChangeCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
- */
-JNIEXPORT void JNICALL Java_com_iotivity_jar_CALeInterface_CALeGattConnectionStateChangeCallback
-  (JNIEnv *env, jobject obj, jobject gatt, jint status, jint newstate)
-{
-    OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status, newstate);
+    CALEClientJniInit();
 
-    if(GATT_SUCCESS == status && STATE_CONNECTED == newstate)  // le connected
+    if (!g_jvm)
     {
-        if(gatt) {
-            CANativeAddGattobjToList(env, gatt);
-            CANativeLEDiscoverServices(env, gatt);
-        }
+        OIC_LOG(ERROR, TAG, "g_jvm is null");
+        return CA_STATUS_FAILED;
     }
-    else if (GATT_SUCCESS == status && STATE_DISCONNECTED == newstate)  // le disconnected
+
+    bool isAttached = false;
+    JNIEnv* env;
+    jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
+    if (JNI_OK != res)
     {
-        if(gatt) {
-            CANativeGattClose(env, gatt);
-            CANativeRemoveGattObj(env, gatt);
+        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;
     }
-    else  // other error
-    {
-        CANativeSendFinsih(env, gatt);
-    }
-}
-
-/*
- * Class:     com_iotivity_jar_CALeInterface
- * Method:    CALeGattServicesDiscoveredCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
- */
-JNIEXPORT void JNICALL Java_com_iotivity_jar_CALeInterface_CALeGattServicesDiscoveredCallback
-  (JNIEnv *env, jobject obj, jobject gatt, jint status)
-{
-    OIC_LOG_V(DEBUG, TAG, "CALeGattServicesDiscoveredCallback - status %d: ", status);
 
-    if(0 != status) // discovery error
+    CAResult_t ret = CALECheckPlatformVersion(env, 18);
+    if (CA_STATUS_OK != ret)
     {
-        CANativeSendFinsih(env, gatt);
-        return;
-    }
+        OIC_LOG(ERROR, TAG, "it is not supported");
 
-    // read Characteristic
-//    CANativeReadCharacteristic(env, gatt);
+        if (isAttached)
+        {
+            (*g_jvm)->DetachCurrentThread(g_jvm);
+        }
 
-    jboolean ret_rx = CANativeSetCharacteristicNoti(env, gatt, IOTIVITY_GATT_RX_UUID);
-    if(!ret_rx) // SetCharacteristicNoti is failed
-    {
-        CANativeSendFinsih(env, gatt);
-        return;
+        return ret;
     }
 
-//        jstring data = (*env)->NewStringUTF(env, "HelloWorld");
-    jobject jni_obj_character = CANativeCreateGattCharacteristic(env, gatt, gSendBuffer);
-    if(!jni_obj_character)
+    ret = CALEClientInitGattMutexVaraibles();
+    if (CA_STATUS_OK != ret)
     {
-        CANativeSendFinsih(env, gatt);
-        return;
-    }
+        OIC_LOG(ERROR, TAG, "CALEClientInitGattMutexVaraibles has failed!");
+        CALEClientTerminateGattMutexVariables();
 
-    sleep(1);
-    jboolean ret = CANativeLESendData(env, gatt, jni_obj_character);
-    if(!ret)
-    {
-        CANativeSendFinsih(env, gatt);
-        return;
-    }
-}
+        if (isAttached)
+        {
+            (*g_jvm)->DetachCurrentThread(g_jvm);
+        }
 
-/*
- * Class:     com_iotivity_jar_CALeInterface
- * Method:    CALeGattCharacteristicReadCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
- */
-JNIEXPORT void JNICALL Java_com_iotivity_jar_CALeInterface_CALeGattCharacteristicReadCallback
-  (JNIEnv *env, jobject obj, jobject gatt, jobject characteristic, jbyteArray data, jint status)
-{
-    OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicReadCallback - status : %d", status);
+        return ret;
+    }
 
-    jboolean isCopy;
-    char* readData = (char*)(*env)->GetByteArrayElements(env, data, &isCopy);
+    g_deviceDescCond = ca_cond_new();
 
-    jstring jni_address = CANativeGetAddressFromGattObj(env, gatt);
-    const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+    // init mutex for send logic
+    g_threadCond = ca_cond_new();
+    g_threadWriteCharacteristicCond = ca_cond_new();
 
-    OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicReadCallback - read data : %s", readData);
+    CALEClientCreateDeviceList();
+    CALEClientJNISetContext();
 
-    gPacketReceiveCallback(address, readData);
-}
+    ret = CALEClientCreateUUIDList();
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CALEClientCreateUUIDList has failed");
 
-/*
- * Class:     com_iotivity_jar_CALeInterface
- * Method:    CALeGattCharacteristicWritjclasseCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
- */
-JNIEXPORT void JNICALL Java_com_iotivity_jar_CALeInterface_CALeGattCharacteristicWriteCallback
-  (JNIEnv *env, jobject obj, jobject gatt, jobject characteristic, jbyteArray data, jint status)
-{
-    OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicWriteCallback - status : %d", status);
+        if (isAttached)
+        {
+            (*g_jvm)->DetachCurrentThread(g_jvm);
+        }
 
-    jboolean isCopy;
-    char* writeData = (char*)(*env)->GetByteArrayElements(env, data, &isCopy);
+        return ret;
+    }
 
-    jstring jni_address = CANativeGetAddressFromGattObj(env, gatt);
-    const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+    ret = CALECreateJniInterfaceObject(); /* create java caleinterface instance*/
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CALECreateJniInterfaceObject has failed");
 
-    OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicWriteCallback - write data : %s", writeData);
+        if (isAttached)
+        {
+            (*g_jvm)->DetachCurrentThread(g_jvm);
+        }
 
-#ifdef DEBUG_MODE
-    CANativeSendFinsih(env, gatt);
-#endif
+        return ret;
+    }
+    g_isStartedLEClient = true;
 
-    if(0 != status)
+    if (isAttached)
     {
-        CANativeSendFinsih(env, gatt);
+        (*g_jvm)->DetachCurrentThread(g_jvm);
     }
+
+    return CA_STATUS_OK;
 }
 
-/*
- * Class:     com_iotivity_jar_CALeInterface
- * Method:    CALeGattCharacteristicChangedCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V
- */
-JNIEXPORT void JNICALL Java_com_iotivity_jar_CALeInterface_CALeGattCharacteristicChangedCallback
-  (JNIEnv *env, jobject obj, jobject gatt, jobject characteristic, jbyteArray data)
+void CALEClientTerminate()
 {
-    OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback");
+    OIC_LOG(DEBUG, TAG, "CALEClientTerminate");
 
-    jboolean isCopy;
-    char* NotificationData = (char*)(*env)->GetByteArrayElements(env, data, &isCopy);
+    if (!g_jvm)
+    {
+        OIC_LOG(ERROR, TAG, "g_jvm is null");
+        return;
+    }
 
-    jstring jni_address = CANativeGetAddressFromGattObj(env, gatt);
-    const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+    bool isAttached = false;
+    JNIEnv* env;
+    jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
+    if (JNI_OK != res)
+    {
+        OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
+        res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
 
-    OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data : %s", NotificationData);
+        if (JNI_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
+            return;
+        }
+        isAttached = true;
+    }
 
-    gPacketReceiveCallback(address, NotificationData);
+    if (g_leScanCallback)
+    {
+        (*env)->DeleteGlobalRef(env, g_leScanCallback);
+    }
 
-    CANativeSendFinsih(env, gatt);
-}
+    if (g_leGattCallback)
+    {
+        (*env)->DeleteGlobalRef(env, g_leGattCallback);
+    }
 
-/*
- * Class:     com_iotivity_jar_CALeInterface
- * Method:    CALeGattDescriptorReadCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
- */
-JNIEXPORT void JNICALL Java_com_iotivity_jar_CALeInterface_CALeGattDescriptorReadCallback
-  (JNIEnv *env, jobject obj, jobject gatt, jobject descriptor, jint status)
-{
-    OIC_LOG_V(DEBUG, TAG, "CALeGattDescriptorReadCallback - status %d: ", status);
-}
+    if (g_sendBuffer)
+    {
+        (*env)->DeleteGlobalRef(env, g_sendBuffer);
+    }
 
-/*
- * Class:     com_iotivity_jar_CALeInterface
- * Method:    CALeGattDescriptorWriteCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
- */
-JNIEXPORT void JNICALL Java_com_iotivity_jar_CALeInterface_CALeGattDescriptorWriteCallback
-  (JNIEnv *env, jobject obj, jobject gatt, jobject descriptor, jint status)
-{
-    OIC_LOG_V(DEBUG, TAG, "CALeGattDescriptorWriteCallback - status %d: ", status);
-}
+    if (g_uuidList)
+    {
+        (*env)->DeleteGlobalRef(env, g_uuidList);
+    }
 
-/*
- * Class:     com_iotivity_jar_CALeInterface
- * Method:    CALeGattReliableWriteCompletedCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
- */
-JNIEXPORT void JNICALL Java_com_iotivity_jar_CALeInterface_CALeGattReliableWriteCompletedCallback
-  (JNIEnv *env, jobject obj, jobject gatt, jint status)
-{
-    OIC_LOG_V(DEBUG, TAG, "CALeGattReliableWriteCompletedCallback - status %d: ", status);
-}
+    CAResult_t ret = CALEClientRemoveAllDeviceState();
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CALEClientRemoveAllDeviceState has failed");
+    }
 
-/*
- * Class:     com_iotivity_jar_CALeInterface
- * Method:    CALeGattReadRemoteRssiCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
- */
-JNIEXPORT void JNICALL Java_com_iotivity_jar_CALeInterface_CALeGattReadRemoteRssiCallback
-  (JNIEnv *env, jobject obj, jobject gatt, jint rssi, jint status)
-{
-    OIC_LOG_V(DEBUG, TAG, "CALeGattReadRemoteRssiCallback - rssi %d,  status %d: ", rssi, status);
-}
+    ret = CALEClientRemoveAllScanDevices(env);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CALEClientRemoveAllScanDevices has failed");
+    }
 
+    ret = CALEClientRemoveAllGattObjs(env);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CALEClientRemoveAllGattObjs has failed");
+    }
 
-void CALEInitialize(u_thread_pool_t handle)
-{
-    OIC_LOG(DEBUG, TAG, "CALEInitialize");
+    g_isStartedMulticastServer = false;
+    CALEClientSetScanFlag(false);
+    CALEClientSetSendFinishFlag(false);
 
-    gThreadPoolHandle = handle;
+    CALEClientTerminateGattMutexVariables();
+    CALEClientDestroyJniInterface();
 
-    // init mutex for send logic
-    gThreadMutex = u_mutex_new();
-    gThreadCond = u_cond_new();
+    ca_cond_free(g_deviceDescCond);
+    ca_cond_free(g_threadCond);
+    ca_cond_free(g_threadWriteCharacteristicCond);
 
-    CANativeCreateUUIDList();
+    g_deviceDescCond = NULL;
+    g_threadCond = NULL;
+    g_threadWriteCharacteristicCond = NULL;
+    g_isSignalSetFlag = false;
+    CALEClientSetAutoConnectFlag(JNI_FALSE);
 
-    CALeCreateJniInterfaceObject(); /* create java CALeInterface instance*/
+    if (isAttached)
+    {
+        (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
 }
 
-void CALETerminate()
+CAResult_t CALEClientDestroyJniInterface()
 {
-    OIC_LOG(DEBUG, TAG, "CALETerminate");
+    OIC_LOG(DEBUG, TAG, "CALEClientDestroyJniInterface");
+
+    if (!g_jvm)
+    {
+        OIC_LOG(ERROR, TAG, "g_jvm is null");
+        return CA_STATUS_FAILED;
+    }
 
-    jboolean isAttached = 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, "Could not get JNIEnv pointer");
+        OIC_LOG(INFO, 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 has failed");
+            return CA_STATUS_FAILED;
         }
-        isAttached = TRUE;
+        isAttached = true;
     }
 
-    CANativeLEDisconnectAll(env);
-
-    if(gLeScanCallback)
+    jclass jni_LeInterface = (*env)->FindClass(env, "org/iotivity/ca/CaLeClientInterface");
+    if (!jni_LeInterface)
     {
-        CANativeLEStopScanImpl(env, gLeScanCallback);
-        sleep(1);
+        OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface class");
+        goto error_exit;
     }
 
-    if(gLeScanCallback)
+    jmethodID jni_InterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_LeInterface,
+                                                                     "destroyLeInterface",
+                                                                     "()V");
+    if (!jni_InterfaceDestroyMethod)
     {
-        (*env)->DeleteGlobalRef(env, gLeScanCallback);
+        OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface destroy method");
+        goto error_exit;
     }
 
-    if(gLeGattCallback)
-    {
-        (*env)->DeleteGlobalRef(env, gLeGattCallback);
-    }
+    (*env)->CallStaticVoidMethod(env, jni_LeInterface, jni_InterfaceDestroyMethod);
 
-    if(gContext)
+    if ((*env)->ExceptionCheck(env))
     {
-        (*env)->DeleteGlobalRef(env, gContext);
+        OIC_LOG(ERROR, TAG, "destroyLeInterface has failed");
+        (*env)->ExceptionDescribe(env);
+        (*env)->ExceptionClear(env);
+        goto error_exit;
     }
 
-    if(gSendBuffer)
-    {
-        (*env)->DeleteGlobalRef(env, gSendBuffer);
-    }
+    OIC_LOG(DEBUG, TAG, "Destroy instance for CaLeClientInterface");
 
-    if(gUUIDList)
+    if (isAttached)
     {
-        (*env)->DeleteGlobalRef(env, gUUIDList);
+        (*g_jvm)->DetachCurrentThread(g_jvm);
     }
 
-    CANativeRemoveAllDevices(env);
-    CANativeRemoveAllGattObjsList(env);
-    gIsStartServer = FALSE;
-    gIsFinishSendData = FALSE;
+    return CA_STATUS_OK;
+
+error_exit:
 
-    if(isAttached)
+    if (isAttached)
+    {
         (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
 
-    // delete mutex object
-    u_mutex_free(gThreadMutex);
-    gThreadMutex = NULL;
-    u_cond_free(gThreadCond);
+    return CA_STATUS_FAILED;
 }
 
-void CANativeSendFinsih(JNIEnv *env, jobject gatt)
+void CALEClientSendFinish(JNIEnv *env, jobject gatt)
 {
-    OIC_LOG_V(DEBUG, TAG, "CANativeSendFinsih");
+    OIC_LOG(DEBUG, TAG, "CALEClientSendFinish");
+    VERIFY_NON_NULL_VOID(env, TAG, "env is null");
 
-    if(gatt)
+    if (gatt)
     {
-        CANativeLEDisconnect(env, gatt);
+        CAResult_t res = CALEClientDisconnect(env, gatt);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
+        }
     }
-    CANativeupdateSendCnt(env);
+    CALEClientUpdateSendCnt(env);
 }
 
-int32_t CALESendUnicastMessage(const char* address, const char* data, uint32_t dataLen)
+CAResult_t CALEClientSendUnicastMessage(const char* address,
+                                        const uint8_t* data,
+                                        const uint32_t dataLen)
 {
-    OIC_LOG_V(DEBUG, TAG, "CALESendUnicastMessage(%s, %s)", address, data);
+    OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessage(%s, %p)", address, data);
+    VERIFY_NON_NULL(address, TAG, "address is null");
+    VERIFY_NON_NULL(data, TAG, "data is null");
 
-    CALESendUnicastMessageImpl(address, data, dataLen);
-    return 0;
+    return CALEClientSendUnicastMessageImpl(address, data, dataLen);
 }
 
-int32_t CALESendMulticastMessage(const char* data, uint32_t dataLen)
+CAResult_t CALEClientSendMulticastMessage(const uint8_t* data,
+                                          const uint32_t dataLen)
 {
-    OIC_LOG_V(DEBUG, TAG, "CALESendMulticastMessage(%s)", data);
+    OIC_LOG_V(DEBUG, TAG, "CALEClientSendMulticastMessage(%p)", data);
+    VERIFY_NON_NULL(data, TAG, "data is null");
+
+    if (!g_jvm)
+    {
+        OIC_LOG(ERROR, TAG, "g_jvm is null");
+        return CA_STATUS_FAILED;
+    }
 
-    jboolean isAttached = 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, "Could not get JNIEnv pointer");
+        OIC_LOG(INFO, 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 0;
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
+            return CA_STATUS_FAILED;
         }
-        isAttached = TRUE;
+        isAttached = true;
     }
 
-    CALESendMulticastMessageImpl(env, data, dataLen);
+    CAResult_t ret = CALEClientSendMulticastMessageImpl(env, data, dataLen);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CALEClientSendMulticastMessageImpl has failed");
+    }
 
-    if(isAttached)
+    if (isAttached)
+    {
         (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
 
-    return 1;
+    return ret;
 }
 
-int32_t CALEStartUnicastServer(const char* address)
+CAResult_t CALEClientStartUnicastServer(const char* address)
 {
-    OIC_LOG_V(DEBUG, TAG, "CALEStartUnicastServer(%s)", address);
+    OIC_LOG_V(DEBUG, TAG, "it is not needed in this platform (%s)", address);
 
-    return 0;
+    return CA_NOT_SUPPORTED;
 }
 
-int32_t CALEStartMulticastServer()
+CAResult_t CALEClientStartMulticastServer()
 {
-    OIC_LOG_V(DEBUG, TAG, "CALEStartMulticastServer");
+    OIC_LOG(DEBUG, TAG, "CALEClientStartMulticastServer");
+
+    if (g_isStartedMulticastServer)
+    {
+        OIC_LOG(ERROR, TAG, "server is already started..it will be skipped");
+        return CA_STATUS_FAILED;
+    }
 
-    if(gIsStartServer)
+    if (!g_jvm)
     {
-        OIC_LOG_V(DEBUG, TAG, "server is already started..it will be skipped");
-        return 0;
+        OIC_LOG(ERROR, TAG, "g_jvm is null");
+        return CA_STATUS_FAILED;
     }
 
-    jboolean isAttached = 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, "Could not get JNIEnv pointer");
+        OIC_LOG(INFO, 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 0;
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
+            return CA_STATUS_FAILED;
         }
-        isAttached = TRUE;
+        isAttached = true;
     }
 
-    gIsStartServer = TRUE;
-
-    CANativeLEStartScan();
+    g_isStartedMulticastServer = true;
+    CAResult_t ret = CALEClientStartScan();
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
+    }
 
-    if(isAttached)
+    if (isAttached)
+    {
         (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
 
-    return 0;
+    return ret;
 }
 
-int32_t CALEStopUnicastServer(int32_t serverID)
+void CALEClientStopUnicastServer()
 {
-    OIC_LOG(DEBUG, TAG, "CALEStopUnicastServer");
-
-    return 0;
+    OIC_LOG(DEBUG, TAG, "CALEClientStopUnicastServer");
 }
 
-int32_t CALEStopMulticastServer(int32_t serverID)
+void CALEClientStopMulticastServer()
 {
-    OIC_LOG(DEBUG, TAG, "CALEStopMulticastServer");
-    gIsStartServer = FALSE;
-    CANativeLEStopScan();
-    return 0;
+    OIC_LOG(DEBUG, TAG, "CALEClientStopMulticastServer");
+    g_isStartedMulticastServer = false;
+    CAResult_t res = CALEClientStopScan();
+    if (CA_STATUS_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
+        return;
+    }
 }
 
-void CALESetCallback(CAPacketReceiveCallback callback)
+void CALEClientSetCallback(CAPacketReceiveCallback callback)
 {
-    gPacketReceiveCallback = callback;
+    g_packetReceiveCallback = callback;
 }
 
-CAResult_t CALEGetInterfaceInfo(char **address)
+void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
 {
-    CALEGetLocalAddress(address);
-    return CA_STATUS_OK;
+    g_clientErrorCallback = callback;
 }
 
-void CALEGetLocalAddress(char** address)
+CAResult_t CALEClientIsThereScannedDevices()
 {
-    jboolean isAttached = FALSE;
-    JNIEnv* env;
-    jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6);
-    if(res != JNI_OK)
+    if (!g_deviceList)
     {
-        OIC_LOG_V(DEBUG, TAG, "Could not get JNIEnv pointer");
-        res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
-        if(res != JNI_OK)
-        {
-            OIC_LOG_V(DEBUG, TAG, "AttachCurrentThread failed");
-            return;
-        }
-        isAttached = TRUE;
+        return CA_STATUS_FAILED;
     }
 
-    jstring jni_address = CANativeGetLocalDeviceAddress(env);
-    if(jni_address)
+    if (0 == u_arraylist_length(g_deviceList))
     {
-        const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
-        *address = (char*)OICMalloc(strlen(localAddress) + 1);
-        if (*address == NULL)
+        // Wait for LE peripherals to be discovered.
+
+        // Number of times to wait for discovery to complete.
+        static size_t const RETRIES = 5;
+
+        static uint64_t const TIMEOUT =
+            2 * MICROSECS_PER_SEC;  // Microseconds
+
+        bool devicesDiscovered = false;
+        for (size_t i = 0;
+             0 == u_arraylist_length(g_deviceList) && i < RETRIES;
+             ++i)
         {
-            return;
+            if (ca_cond_wait_for(g_deviceDescCond,
+                                 g_threadSendMutex,
+                                 TIMEOUT) == CA_WAIT_SUCCESS)
+            {
+                devicesDiscovered = true;
+                break;
+            }
+        }
+
+        // time out for scanning devices
+        if (!devicesDiscovered)
+        {
+            return CA_STATUS_FAILED;
         }
-        memcpy(*address, localAddress, strlen(localAddress));
     }
 
-    OIC_LOG_V(DEBUG, TAG, "Local Address : %s", *address);
-    if(isAttached)
-        (*g_jvm)->DetachCurrentThread(g_jvm);
+    return CA_STATUS_OK;
 }
 
-int32_t CALESendUnicastMessageImpl(const char* address, const char* data, uint32_t dataLen)
+CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t* data,
+                                      const uint32_t dataLen)
 {
-    OIC_LOG_V(DEBUG, TAG, "CALESendUnicastMessageImpl, address: %s, data: %s", address, data);
+    OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessageImpl, address: %s, data: %p", address,
+              data);
+    VERIFY_NON_NULL(address, TAG, "address is null");
+    VERIFY_NON_NULL(data, TAG, "data is null");
 
-    jboolean isAttached = FALSE;
+    if (!g_jvm)
+    {
+        OIC_LOG(ERROR, TAG, "g_jvm is null");
+        return CA_STATUS_FAILED;
+    }
+
+    bool isAttached = false;
     JNIEnv* env;
-    jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6);
-    if(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, "Could not get JNIEnv pointer");
+        OIC_LOG(INFO, 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 0;
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
+            return CA_STATUS_FAILED;
         }
-        isAttached = TRUE;
+        isAttached = true;
     }
 
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] set byteArray for data");
-    if(gSendBuffer)
+    ca_mutex_lock(g_threadSendMutex);
+
+    CALEClientSetSendFinishFlag(false);
+
+    CAResult_t ret = CALEClientIsThereScannedDevices();
+    if (CA_STATUS_OK != ret)
     {
-        (*env)->DeleteGlobalRef(env, gSendBuffer);
+        OIC_LOG(INFO, TAG, "there is no scanned device");
+        goto error_exit;
     }
-    jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
-    (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*)data);
-    gSendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
-
-    // connect to gatt server
-    CANativeLEStopScanImpl(env, gLeScanCallback);
-    sleep(1);
 
-    jobject jni_obj_bluetoothDevice = NULL;
-    if(gContext && gdeviceList)
+    if (g_context && g_deviceList)
     {
-        jint index;
-        for (index = 0; index < u_arraylist_length(gdeviceList); index++)
+        uint32_t length = u_arraylist_length(g_deviceList);
+        for (uint32_t index = 0; index < length; index++)
         {
-            jobject jarrayObj = (jobject) u_arraylist_get(gdeviceList, index);
-            if(!jarrayObj)
+            jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
+            if (!jarrayObj)
             {
-                OIC_LOG(DEBUG, TAG, "[BLE][Native] jarrayObj is null");
-                return 0;
+                OIC_LOG(ERROR, TAG, "jarrayObj is null");
+                goto error_exit;
             }
 
-            jstring jni_setAddress = CANativeGetAddressFromBTDevice(env, jarrayObj);
-            if(!jni_setAddress)
+            jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
+            if (!jni_setAddress)
             {
-                OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_setAddress is null");
-                return 0;
+                OIC_LOG(ERROR, TAG, "jni_setAddress is null");
+                goto error_exit;
             }
+
             const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
+            if (!setAddress)
+            {
+                OIC_LOG(ERROR, TAG, "setAddress is null");
+                goto error_exit;
+            }
+
+            OIC_LOG_V(DEBUG, TAG, "remote device address is %s", setAddress);
 
-            if(!strcmp(setAddress, address))
+            if (!strcmp(setAddress, address))
             {
-                jni_obj_bluetoothDevice = jarrayObj;
+                (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+
+                // connect to gatt server
+                ret = CALEClientStopScan();
+                if (CA_STATUS_OK != ret)
+                {
+                    OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
+                    goto error_exit;
+                }
+
+                if (g_sendBuffer)
+                {
+                    (*env)->DeleteGlobalRef(env, g_sendBuffer);
+                    g_sendBuffer = NULL;
+                }
+                jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
+                (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
+                g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
+
+                // Target device to send message is just one.
+                g_targetCnt = 1;
+
+                ret = CALEClientSendData(env, jarrayObj);
+                if (CA_STATUS_OK != ret)
+                {
+                    OIC_LOG(ERROR, TAG, "CALEClientSendData in unicast is failed");
+                    goto error_exit;
+                }
+
+                OIC_LOG(INFO, TAG, "wake up");
                 break;
             }
-        }
-
-        if(jni_obj_bluetoothDevice)
-        {
-            jboolean autoConnect = FALSE;
-            CANativeLEConnect(env, jni_obj_bluetoothDevice, gContext, autoConnect, gLeGattCallback);
+            (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
         }
     }
 
-    if(isAttached)
-        (*g_jvm)->DetachCurrentThread(g_jvm);
-
-    return 1;
-}
-
-int32_t CALESendMulticastMessageImpl(JNIEnv *env, const char* data, uint32_t dataLen)
-{
-    OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %s, %d", data, dataLen);
+    OIC_LOG(DEBUG, TAG, "connection routine is finished for unicast");
 
-    if(!gdeviceList)
+    // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
+    // if there is no connection state.
+    ca_mutex_lock(g_threadMutex);
+    if (!g_isFinishedSendData)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] gdeviceList is null");
-        return 0;
+        OIC_LOG(DEBUG, TAG, "waiting send finish signal");
+        ca_cond_wait(g_threadCond, g_threadMutex);
+        OIC_LOG(DEBUG, TAG, "the data was sent");
     }
-    OIC_LOG(DEBUG, TAG, "set wait");
-
+    ca_mutex_unlock(g_threadMutex);
 
-    gIsFinishSendData = FALSE;
+    if (isAttached)
+    {
+        (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
 
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] set byteArray for data");
-    if(gSendBuffer)
+    // start LE Scan again
+    ret = CALEClientStartScan();
+    if (CA_STATUS_OK != ret)
     {
-        (*env)->DeleteGlobalRef(env, gSendBuffer);
+        OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
+        ca_mutex_unlock(g_threadSendMutex);
+        return res;
     }
-    jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
-    (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*)data);
-    gSendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
 
-    // connect to gatt server
-    CANativeLEStopScanImpl(env, gLeScanCallback);
-    sleep(1);
+    ca_mutex_unlock(g_threadSendMutex);
+    OIC_LOG(INFO, TAG, "unicast - send logic has finished");
+    return CALECheckSendState(address);
 
-    // reset gatt list
-    CANativeRemoveAllGattObjsList(env);
-    CANativeCreateGattObjList(env);
+    // error label.
+error_exit:
 
-    gTargetCnt = u_arraylist_length(gdeviceList);
-
-    jint index = 0;
-
-    while (index < u_arraylist_length(gdeviceList)) {
-        jobject jarrayObj = (jobject) u_arraylist_get(gdeviceList, index);
-        if(!jarrayObj)
-        {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] jarrayObj is null");
-            continue;
-        }
-
-        if(0 <= CANativeLEConnect(env, jarrayObj, gContext, FALSE, gLeGattCallback))
+    // start LE Scan again
+    ret = CALEClientStartScan();
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
+        ca_mutex_unlock(g_threadSendMutex);
+        if (isAttached)
         {
-            // connection failure
-            index++;
+            (*g_jvm)->DetachCurrentThread(g_jvm);
         }
-        sleep(1);
+        return res;
     }
 
-    // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
-    if(!gIsFinishSendData)
+    if (isAttached)
     {
-        u_mutex_lock(gThreadMutex);
-        u_cond_wait(gThreadCond, gThreadMutex);
-        OIC_LOG(DEBUG, TAG, "unset wait");
-        u_mutex_unlock(gThreadMutex);
+        (*g_jvm)->DetachCurrentThread(g_jvm);
     }
 
-    // start LE Scan again
-#ifdef DEBUG_MODE
-    CANativeLEStartScan();
-#endif
-
-    return 1;
+    if (g_clientErrorCallback)
+    {
+        g_clientErrorCallback(address, data, dataLen, CA_SEND_FAILED);
+    }
+    ca_mutex_unlock(g_threadSendMutex);
+    return CA_SEND_FAILED;
 }
 
-/**
- * BT common
- */
-jstring CANativeGetLocalDeviceAddress(JNIEnv* env)
+CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data,
+                                              const uint32_t dataLen)
 {
-    jclass jni_cid_BTAdapter = (*env)->FindClass(env,  CLASSPATH_BT_ADPATER);
-    if(!jni_cid_BTAdapter)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] getAddress: jni_cid_BTAdapter is null");
-        return NULL;
-    }
+    OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %p, %u", data, dataLen);
+    VERIFY_NON_NULL(data, TAG, "data is null");
+    VERIFY_NON_NULL(env, TAG, "env is null");
 
-    jmethodID jni_mid_getDefaultAdapter =
-            (*env)->GetStaticMethodID(env, jni_cid_BTAdapter, "getDefaultAdapter", METHODID_OBJECTNONPARAM);
-    if(!jni_mid_getDefaultAdapter)
+    if (!g_deviceList)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] getAddress: jni_mid_getDefaultAdapter is null");
-        return NULL;
+        OIC_LOG(ERROR, TAG, "g_deviceList is null");
+        return CA_STATUS_FAILED;
     }
 
-    jmethodID jni_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTAdapter, "getAddress", METHODID_STRINGNONPARAM);
-    if(!jni_mid_getAddress)
+    ca_mutex_lock(g_threadSendMutex);
+
+    CALEClientSetSendFinishFlag(false);
+
+    OIC_LOG(DEBUG, TAG, "set byteArray for data");
+    if (g_sendBuffer)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] getAddress: jni_mid_getAddress is null");
-        return NULL;
+        (*env)->DeleteGlobalRef(env, g_sendBuffer);
+        g_sendBuffer = NULL;
     }
 
-    jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter, jni_mid_getDefaultAdapter);
-    if(!jni_obj_BTAdapter)
+    CAResult_t res = CALEClientIsThereScannedDevices();
+    if (CA_STATUS_OK != res)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] getAddress: jni_obj_BTAdapter is null");
-        return NULL;
+        OIC_LOG(INFO, TAG, "there is no scanned device");
+        goto error_exit;
     }
 
-    jstring jni_str_address = (jstring)(*env)->CallObjectMethod(env, jni_obj_BTAdapter, jni_mid_getAddress);
-    if(!jni_str_address)
+    // connect to gatt server
+    res = CALEClientStopScan();
+    if (CA_STATUS_OK != res)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] getAddress: jni_str_address is null");
-        return NULL;
+        OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
+        ca_mutex_unlock(g_threadSendMutex);
+        return res;
     }
+    uint32_t length = u_arraylist_length(g_deviceList);
+    g_targetCnt = length;
 
-    return jni_str_address;
-}
+    jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
+    (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
+    g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
 
-jobjectArray CANativeBondedDevices(JNIEnv *env)
-{
-    jclass jni_cid_BTAdapter = (*env)->FindClass(env,  CLASSPATH_BT_ADPATER);
-    if(!jni_cid_BTAdapter)
+    for (uint32_t index = 0; index < length; index++)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] getBondedDevices: jni_cid_BTAdapter is null");
-        return NULL;
-    }
+        jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
+        if (!jarrayObj)
+        {
+            OIC_LOG(ERROR, TAG, "jarrayObj is not available");
+            continue;
+        }
 
-    jmethodID jni_mid_getDefaultAdapter =
-            (*env)->GetStaticMethodID(env, jni_cid_BTAdapter, "getDefaultAdapter", METHODID_OBJECTNONPARAM);
+        res = CALEClientSendData(env, jarrayObj);
+        if (res != CA_STATUS_OK)
+        {
+            OIC_LOG(ERROR, TAG, "BT device - send has failed");
+        }
 
-    jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter, jni_mid_getDefaultAdapter);
-    if(!jni_obj_BTAdapter)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] getBondedDevices: bluetooth adapter is null");
-        return NULL;
-    }
+        jstring jni_address = CALEGetAddressFromBTDevice(env, jarrayObj);
+        if (!jni_address)
+        {
+            OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
+            continue;
+        }
 
-    // Get a list of currently paired devices
-    jmethodID jni_mid_getBondedDevices = (*env)->GetMethodID(env, jni_cid_BTAdapter,
-            "getBondedDevices", "()Ljava/util/Set;");
-    if(!jni_mid_getBondedDevices)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] getBondedDevices: jni_mid_getBondedDevicesr is null");
-        return NULL;
+        const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+        if (!address)
+        {
+            OIC_LOG(ERROR, TAG, "address is not available");
+            continue;
+        }
+
+        (*env)->ReleaseStringUTFChars(env, jni_address, address);
     }
 
-    jobject jni_obj_setPairedDevices = (*env)->CallObjectMethod(env, jni_obj_BTAdapter, jni_mid_getBondedDevices);
-    if(!jni_obj_setPairedDevices)
+    OIC_LOG(DEBUG, TAG, "connection routine is finished for multicast");
+
+    // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
+    ca_mutex_lock(g_threadMutex);
+    if (!g_isFinishedSendData)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] getBondedDevices: jni_obj_setPairedDevices is null");
-        return NULL;
+        OIC_LOG(DEBUG, TAG, "waiting send finish signal");
+        ca_cond_wait(g_threadCond, g_threadMutex);
+        OIC_LOG(DEBUG, TAG, "the data was sent");
     }
+    ca_mutex_unlock(g_threadMutex);
 
-    // Convert the set to an object array
-    // object[] array = Set<BluetoothDevice>.toArray();
-    jclass jni_cid_Set = (*env)->FindClass(env,  "java/util/Set");
-    jmethodID jni_mid_toArray = (*env)->GetMethodID(env, jni_cid_Set, "toArray", "()[Ljava/lang/Object;");
-
-    if(!jni_mid_toArray)
+    // start LE Scan again
+    res = CALEClientStartScan();
+    if (CA_STATUS_OK != res)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] getBondedDevices: jni_mid_toArray is null");
-        return NULL;
+        OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
+        ca_mutex_unlock(g_threadSendMutex);
+        return res;
     }
 
-    jobjectArray jni_arrayPairedDevices = (jobjectArray)((*env)->CallObjectMethod(env,
-            jni_obj_setPairedDevices, jni_mid_toArray));
-    if(!jni_arrayPairedDevices)
+    ca_mutex_unlock(g_threadSendMutex);
+    OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl");
+    return CA_STATUS_OK;
+
+error_exit:
+    res = CALEClientStartScan();
+    if (CA_STATUS_OK != res)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] getBondedDevices: jni_arrayPairedDevices is null");
-        return NULL;
+        OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
+        ca_mutex_unlock(g_threadSendMutex);
+        return res;
     }
 
-    return jni_arrayPairedDevices;
+    ca_mutex_unlock(g_threadSendMutex);
+    OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl");
+    return CA_SEND_FAILED;
 }
 
-jint CANativeGetBTStateOnInfo(JNIEnv *env)
+CAResult_t CALECheckSendState(const char* address)
 {
-    jclass jni_cid_BTAdapter = (*env)->FindClass(env,  CLASSPATH_BT_ADPATER);
-    if(!jni_cid_BTAdapter)
+    VERIFY_NON_NULL(address, TAG, "address is null");
+
+    ca_mutex_lock(g_deviceStateListMutex);
+    CALEState_t* state = CALEClientGetStateInfo(address);
+    if (NULL == state)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] getBTStateOnInfo: jni_cid_BTAdapter is null");
-        return -1;
+        OIC_LOG(ERROR, TAG, "state is null");
+        ca_mutex_unlock(g_deviceStateListMutex);
+        return CA_SEND_FAILED;
     }
 
-    jfieldID jni_fid_stateon = (*env)->GetStaticFieldID(env, jni_cid_BTAdapter, "STATE_ON", "I");
-    if (jni_fid_stateon == 0)
+    if (STATE_SEND_SUCCESS != state->sendState)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] get_field_state is 0");
-        return -1;
+        OIC_LOG(ERROR, TAG, "sendstate is not STATE_SEND_SUCCESS");
+        ca_mutex_unlock(g_deviceStateListMutex);
+        return CA_SEND_FAILED;
     }
-    jint jni_int_val = (*env)->GetStaticIntField(env, jni_cid_BTAdapter, jni_fid_stateon);
-
-    OIC_LOG_V(DEBUG, TAG, "[BLE][Native] bluetooth STATE_ON state integer value : %d", jni_int_val);
 
-    return jni_int_val;
+    OIC_LOG(INFO, TAG, "sendstate is STATE_SEND_SUCCESS");
+    ca_mutex_unlock(g_deviceStateListMutex);
+    return CA_STATUS_OK;
 }
 
-jboolean CANativeIsEnableBTAdapter(JNIEnv *env)
+CAResult_t CALEClientSendData(JNIEnv *env, jobject device)
 {
-    jclass jni_cid_BTAdapter = (*env)->FindClass(env,  CLASSPATH_BT_ADPATER);
-    if(!jni_cid_BTAdapter)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_cid_BTAdapter: jni_cid_BTAdapter is null");
-        return FALSE;
+    OIC_LOG(DEBUG, TAG, "IN - CALEClientSendData");
+    VERIFY_NON_NULL(device, TAG, "device is null");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+
+    // get BLE address from bluetooth device object.
+    char* address = NULL;
+    CALEState_t* state = NULL;
+    jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, device);
+    if (jni_address)
+    {
+        OIC_LOG(INFO, TAG, "there is gatt object..it's not first connection");
+        address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
+        if (!address)
+        {
+            OIC_LOG(ERROR, TAG, "address is not available");
+            return CA_STATUS_FAILED;
+        }
+        ca_mutex_lock(g_deviceStateListMutex);
+        state = CALEClientGetStateInfo(address);
+        ca_mutex_unlock(g_deviceStateListMutex);
+        (*env)->ReleaseStringUTFChars(env, jni_address, address);
     }
 
-    jmethodID jni_mid_getDefaultAdapter =
-            (*env)->GetStaticMethodID(env, jni_cid_BTAdapter, "getDefaultAdapter", METHODID_OBJECTNONPARAM);
-    if(!jni_mid_getDefaultAdapter)
+    if (!state)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_mid_getDefaultAdapter is null");
-        return FALSE;
-    }
+        OIC_LOG(DEBUG, TAG, "state is empty..start to connect LE");
 
-    jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter, jni_mid_getDefaultAdapter);
-    if(!jni_obj_BTAdapter)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_obj_BTAdapter is null");
-        return FALSE;
-    }
+        // cancel previous connection request before connection
+        // if there is gatt object in g_gattObjectList.
+        if (jni_address)
+        {
+            address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
+            if (!address)
+            {
+                OIC_LOG(ERROR, TAG, "address is not available");
+                return CA_STATUS_FAILED;
+            }
 
-    // isEnable()
-    jmethodID jni_mid_isEnable = (*env)->GetMethodID(env, jni_cid_BTAdapter, "isEnabled",
-            "()Z");
-    if(!jni_mid_isEnable)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_mid_isEnable is null");
-        return FALSE;
+            jobject gatt = CALEClientGetGattObjInList(env, address);
+            if (gatt)
+            {
+                CAResult_t res = CALEClientDisconnect(env, gatt);
+                if (CA_STATUS_OK != res)
+                {
+                    OIC_LOG(INFO, TAG, "there is no gatt object");
+                }
+            }
+            (*env)->ReleaseStringUTFChars(env, jni_address, address);
+        }
+
+        // connection request
+        jobject newGatt = CALEClientConnect(env, device, CALEClientGetAutoConnectFlag());
+        if (NULL == newGatt)
+        {
+            OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
+            return CA_STATUS_FAILED;
+        }
     }
+    else
+    {
+        if (STATE_CONNECTED == state->connectedState)
+        {
+            OIC_LOG(INFO, TAG, "GATT has already connected");
+            if (!jni_address)
+            {
+                OIC_LOG(ERROR, TAG, "jni_address is not available");
+                return CA_STATUS_FAILED;
+            }
 
-    jboolean jni_isEnable = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter, jni_mid_isEnable);
-    OIC_LOG_V(DEBUG, TAG, "[BLE][Native] adapter state is %d", jni_isEnable);
+            address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
+            if (!address)
+            {
+                OIC_LOG(ERROR, TAG, "address is not available");
+                return CA_STATUS_FAILED;
+            }
 
-    return jni_isEnable;
-}
+            jobject gatt = CALEClientGetGattObjInList(env, address);
+            if (!gatt)
+            {
+                OIC_LOG(ERROR, TAG, "CALEClientGetGattObjInList has failed");
+                (*env)->ReleaseStringUTFChars(env, jni_address, address);
+                return CA_STATUS_FAILED;
+            }
 
-jstring CANativeGetAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice)
-{
-    jclass jni_cid_device_list = (*env)->FindClass(env, "android/bluetooth/BluetoothDevice");
-    if(!jni_cid_device_list)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_cid_device_list is null");
-        return NULL;
-    }
+            CAResult_t ret = CALESetValueAndWriteCharacteristic(env, gatt);
+            if (CA_STATUS_OK != ret)
+            {
+                OIC_LOG(ERROR, TAG, "CALESetValueAndWriteCharacteristic has failed");
+                (*env)->ReleaseStringUTFChars(env, jni_address, address);
+                return ret;
+            }
+            (*env)->ReleaseStringUTFChars(env, jni_address, address);
+        }
+        else
+        {
+            OIC_LOG(INFO, TAG, "STATE_DISCONNECTED - start to connect LE");
 
-    jmethodID jni_mid_getAddress = (*env)->GetMethodID(env, jni_cid_device_list, "getAddress",
-            "()Ljava/lang/String;");
-    if(!jni_mid_getAddress)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_mid_getAddress is null");
-        return NULL;
-    }
+            // cancel previous connection request before connection
+            // if there is gatt object in g_gattObjectList.
+            if (jni_address)
+            {
+                address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
+                if (!address)
+                {
+                    OIC_LOG(ERROR, TAG, "address is not available");
+                    return CA_STATUS_FAILED;
+                }
+
+                jobject gatt = CALEClientGetGattObjInList(env, address);
+                if (gatt)
+                {
+                    CAResult_t res = CALEClientDisconnect(env, gatt);
+                    if (CA_STATUS_OK != res)
+                    {
+                        OIC_LOG(INFO, TAG, "there is no gatt object");
+                    }
+                }
+                (*env)->ReleaseStringUTFChars(env, jni_address, address);
+            }
 
-    jstring jni_address = (jstring)(*env)->CallObjectMethod(env, bluetoothDevice, jni_mid_getAddress);
-    if(!jni_address)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_address is null");
-        return NULL;
+            OIC_LOG(DEBUG, TAG, "start to connect LE");
+            jobject gatt = CALEClientConnect(env, device, JNI_TRUE);
+            if (NULL == gatt)
+            {
+                OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
+                return CA_STATUS_FAILED;
+            }
+        }
     }
-    return jni_address;
+
+    return CA_STATUS_OK;
 }
 
-jstring CANativeGetAddressFromGattObj(JNIEnv *env, jobject gatt)
+jstring CALEClientGetAddressFromGattObj(JNIEnv *env, jobject gatt)
 {
-    if(!gatt)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] gatt is null");
-        return NULL;
-    }
+    VERIFY_NON_NULL_RET(gatt, TAG, "gatt is null", NULL);
+    VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
 
     jclass jni_cid_gattdevice_list = (*env)->FindClass(env, CLASSPATH_BT_GATT);
-    if(!jni_cid_gattdevice_list)
+    if (!jni_cid_gattdevice_list)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_cid_gattdevice_list is null");
+        OIC_LOG(ERROR, TAG, "jni_cid_gattdevice_list is null");
         return NULL;
     }
 
     jmethodID jni_mid_getDevice = (*env)->GetMethodID(env, jni_cid_gattdevice_list, "getDevice",
-            "()Landroid/bluetooth/BluetoothDevice;");
-    if(!jni_mid_getDevice)
+                                                      "()Landroid/bluetooth/BluetoothDevice;");
+    if (!jni_mid_getDevice)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_mid_getDevice is null");
+        OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
         return NULL;
     }
 
     jobject jni_obj_device = (*env)->CallObjectMethod(env, gatt, jni_mid_getDevice);
-    if(!jni_obj_device)
+    if (!jni_obj_device)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_obj_device is null");
+        OIC_LOG(ERROR, TAG, "jni_obj_device is null");
         return NULL;
     }
 
-    jstring jni_address = CANativeGetAddressFromBTDevice(env, jni_obj_device);
-    if(!jni_address)
+    jstring jni_address = CALEGetAddressFromBTDevice(env, jni_obj_device);
+    if (!jni_address)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_address is null");
+        OIC_LOG(ERROR, TAG, "jni_address is null");
         return NULL;
     }
 
@@ -953,1125 +1099,3197 @@ jstring CANativeGetAddressFromGattObj(JNIEnv *env, jobject gatt)
 /**
  * BLE layer
  */
-void CANativeGattClose(JNIEnv *env, jobject bluetoothGatt)
+CAResult_t CALEClientGattClose(JNIEnv *env, jobject bluetoothGatt)
 {
     // GATT CLOSE
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] GATT CLOSE");
+    OIC_LOG(DEBUG, TAG, "Gatt Close");
+    VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
+    VERIFY_NON_NULL(env, TAG, "env is null");
 
     // get BluetoothGatt class
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] get BluetoothGatt class");
+    OIC_LOG(DEBUG, TAG, "get BluetoothGatt class");
     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
-    if(!jni_cid_BluetoothGatt)
+    if (!jni_cid_BluetoothGatt)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_cid_BluetoothGatt is null");
-        return;
+        OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
+        return CA_STATUS_FAILED;
     }
 
-    jmethodID jni_mid_closeGatt = (*env)->GetMethodID(env, jni_cid_BluetoothGatt, "close","()V");
-    if(!jni_mid_closeGatt)
+    jmethodID jni_mid_closeGatt = (*env)->GetMethodID(env, jni_cid_BluetoothGatt, "close", "()V");
+    if (!jni_mid_closeGatt)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_mid_closeGatt is null");
-        return;
+        OIC_LOG(ERROR, TAG, "jni_mid_closeGatt is null");
+        return CA_STATUS_OK;
     }
 
     // call disconnect gatt method
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] request close Gatt");
+    OIC_LOG(DEBUG, TAG, "request to close GATT");
     (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_closeGatt);
+
+    if ((*env)->ExceptionCheck(env))
+    {
+        OIC_LOG(ERROR, TAG, "closeGATT has failed");
+        (*env)->ExceptionDescribe(env);
+        (*env)->ExceptionClear(env);
+        return CA_STATUS_FAILED;
+    }
+
+    return CA_STATUS_OK;
 }
 
-void CANativeLEStartScan()
+CAResult_t CALEClientStartScan()
 {
-    if(!gIsStartServer)
+    if (!g_isStartedMulticastServer)
     {
-        OIC_LOG_V(DEBUG, TAG, "server is not started yet..scan will be passed");
-        return;
+        OIC_LOG(ERROR, TAG, "server is not started yet..scan will be passed");
+        return CA_STATUS_FAILED;
+    }
+
+    if (!g_isStartedLEClient)
+    {
+        OIC_LOG(ERROR, TAG, "LE client is not started");
+        return CA_STATUS_FAILED;
+    }
+
+    if (!g_jvm)
+    {
+        OIC_LOG(ERROR, TAG, "g_jvm is null");
+        return CA_STATUS_FAILED;
+    }
+
+    if (g_isStartedScan)
+    {
+        OIC_LOG(INFO, TAG, "scanning is already started");
+        return CA_STATUS_OK;
     }
 
-    jboolean isAttached = 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, "Could not get JNIEnv pointer");
+        OIC_LOG(INFO, 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 has failed");
+            return CA_STATUS_FAILED;
         }
-        isAttached = TRUE;
+        isAttached = true;
     }
 
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeLEStartScan");
+    OIC_LOG(DEBUG, TAG, "CALEClientStartScan");
 
+    CAResult_t ret = CA_STATUS_OK;
     // scan gatt server with UUID
-    if(gLeScanCallback && gUUIDList)
+    if (g_leScanCallback && g_uuidList)
     {
-        CANativeLEStartScanWithUUIDImpl(env, gUUIDList, gLeScanCallback);
+#ifdef UUID_SCAN
+        ret = CALEClientStartScanWithUUIDImpl(env, g_uuidList, g_leScanCallback);
+#else
+        ret = CALEClientStartScanImpl(env, g_leScanCallback);
+#endif
+        if (CA_STATUS_OK != ret)
+        {
+            if (CA_ADAPTER_NOT_ENABLED == ret)
+            {
+                OIC_LOG(DEBUG, TAG, "Adapter is disabled");
+            }
+            else
+            {
+                OIC_LOG(ERROR, TAG, "start scan has failed");
+            }
+        }
     }
 
-    if(isAttached)
+    if (isAttached)
+    {
         (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
 
+    return ret;
 }
 
-void CANativeLEStartScanImpl(JNIEnv *env, jobject callback)
+CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback)
 {
-    if(!CANativeIsEnableBTAdapter(env))
+    VERIFY_NON_NULL(callback, TAG, "callback is null");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+
+    if (!CALEIsEnableBTAdapter(env))
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] BT adpater is not enable");
-        return;
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return CA_ADAPTER_NOT_ENABLED;
     }
 
     // get default bt adapter class
-    jclass jni_cid_BTAdapter = (*env)->FindClass(env,  CLASSPATH_BT_ADPATER);
-    if(!jni_cid_BTAdapter)
+    jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
+    if (!jni_cid_BTAdapter)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] getState From BTAdapter: jni_cid_BTAdapter is null");
-        return;
+        OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
+        return CA_STATUS_FAILED;
     }
 
     // get remote bt adapter method
-    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, "[BLE][Native] getState From BTAdapter: jni_mid_getDefaultAdapter is null");
-        return;
+        OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
+        return CA_STATUS_FAILED;
     }
 
     // get start le scan method
     jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
-            "(Landroid/bluetooth/BluetoothAdapter$LeScanCallback;)Z");
-    if(!jni_mid_startLeScan)
+                                                        "(Landroid/bluetooth/BluetoothAdapter$"
+                                                        "LeScanCallback;)Z");
+    if (!jni_mid_startLeScan)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] startLeScan: jni_mid_startLeScan is null");
-        return;
+        OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
+        return CA_STATUS_FAILED;
     }
 
     // gat bt adapter object
-    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, "[BLE][Native] getState From BTAdapter: jni_obj_BTAdapter is null");
-        return;
+        OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
+        return CA_STATUS_FAILED;
     }
 
     // call start le scan method
-    jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter, jni_mid_startLeScan, callback);
-    if(!jni_obj_startLeScan)
+    jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
+                                                             jni_mid_startLeScan, callback);
+    if (!jni_obj_startLeScan)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] startLeScan is failed");
-        return;
+        OIC_LOG(ERROR, TAG, "startLeScan is failed");
+        return CA_STATUS_FAILED;
     }
     else
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] startLeScan is started");
-    }
-}
-
-jobject CANativeGetUUIDObject(JNIEnv *env, const char* uuid)
-{
-    // setting UUID
-    jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
-    if(!jni_cid_uuid)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_cid_uuid 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)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_mid_fromString is null");
-        return NULL;
-    }
-
-    jstring jni_uuid = (*env)->NewStringUTF(env, uuid);
-    jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString, jni_uuid);
-    if(!jni_obj_uuid)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_obj_uuid is null");
-        return NULL;
+        OIC_LOG(DEBUG, TAG, "startLeScan is started");
+        CALEClientSetScanFlag(true);
     }
 
-    return jni_obj_uuid;
+    return CA_STATUS_OK;
 }
 
-void CANativeLEStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobject callback)
+CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobject callback)
 {
-    // get default bt adapter class
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] get default bt adapter class");
+    VERIFY_NON_NULL(callback, TAG, "callback is null");
+    VERIFY_NON_NULL(uuids, TAG, "uuids is null");
+    VERIFY_NON_NULL(env, TAG, "env is null");
 
-    if(!CANativeIsEnableBTAdapter(env))
+    if (!CALEIsEnableBTAdapter(env))
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] BT adpater is not enable");
-        return;
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return CA_ADAPTER_NOT_ENABLED;
     }
 
-    jclass jni_cid_BTAdapter = (*env)->FindClass(env,  CLASSPATH_BT_ADPATER);
-    if(!jni_cid_BTAdapter)
+    jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
+    if (!jni_cid_BTAdapter)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] getState From BTAdapter: jni_cid_BTAdapter is null");
-        return;
+        OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
+        return CA_STATUS_FAILED;
     }
 
     // get remote bt adapter method
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] get remote bt adapter method");
-    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, "[BLE][Native] getState From BTAdapter: jni_mid_getDefaultAdapter is null");
-        return;
+        OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
+        return CA_STATUS_FAILED;
     }
 
     // get start le scan method
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] get start le scan method");
     jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
-            "([Ljava/util/UUID;Landroid/bluetooth/BluetoothAdapter$LeScanCallback;)Z");
-    if(!jni_mid_startLeScan)
+                                                        "([Ljava/util/UUID;Landroid/bluetooth/"
+                                                        "BluetoothAdapter$LeScanCallback;)Z");
+    if (!jni_mid_startLeScan)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] startLeScan: jni_mid_startLeScan is null");
-        return;
+        OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
+        return CA_STATUS_FAILED;
     }
 
     // get bt adapter object
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] get bt adapter object");
-    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, "[BLE][Native] getState From BTAdapter: jni_obj_BTAdapter is null");
-        return;
+        OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
+        return CA_STATUS_FAILED;
     }
 
     // call start le scan method
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] call start le scan service method");
-    jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter, jni_mid_startLeScan, uuids, callback);
-    if(!jni_obj_startLeScan)
+    jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
+                                                             jni_mid_startLeScan, uuids, callback);
+    if (!jni_obj_startLeScan)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] startLeScan With UUID is failed");
-        return;
+        OIC_LOG(ERROR, TAG, "startLeScan With UUID is failed");
+        return CA_STATUS_FAILED;
     }
     else
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] startLeScan With UUID is started");
+        OIC_LOG(DEBUG, TAG, "startLeScan With UUID is started");
+        CALEClientSetScanFlag(true);
+    }
+
+    return CA_STATUS_OK;
+}
+
+jobject CALEClientGetUUIDObject(JNIEnv *env, const char* uuid)
+{
+    VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL);
+    VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
+
+    // setting UUID
+    jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
+    if (!jni_cid_uuid)
+    {
+        OIC_LOG(ERROR, TAG, "jni_cid_uuid 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)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
+        return NULL;
+    }
+
+    jstring jni_uuid = (*env)->NewStringUTF(env, uuid);
+    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;
     }
+
+    return jni_obj_uuid;
 }
 
-void CANativeLEStopScan()
+CAResult_t CALEClientStopScan()
 {
-    jboolean isAttached = FALSE;
+    if (!g_jvm)
+    {
+        OIC_LOG(ERROR, TAG, "g_jvm is null");
+        return CA_STATUS_FAILED;
+    }
+
+    if (!g_isStartedScan)
+    {
+        OIC_LOG(INFO, TAG, "scanning is already stopped");
+        return CA_STATUS_OK;
+    }
+
+    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, "Could not get JNIEnv pointer");
+        OIC_LOG(INFO, 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 has failed");
+            return CA_STATUS_FAILED;
         }
-        isAttached = TRUE;
+        isAttached = true;
     }
 
-    CANativeLEStopScanImpl(env, gLeScanCallback);
+    CAResult_t ret = CALEClientStopScanImpl(env, g_leScanCallback);
+    if (CA_STATUS_OK != ret)
+    {
+        if (CA_ADAPTER_NOT_ENABLED == ret)
+        {
+            OIC_LOG(DEBUG, TAG, "Adapter is disabled");
+        }
+        else
+        {
+            OIC_LOG(ERROR, TAG, "CALEClientStopScanImpl has failed");
+        }
+    }
+    else
+    {
+        CALEClientSetScanFlag(false);
+    }
 
-    if(isAttached)
+    if (isAttached)
+    {
         (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
+
+    return ret;
+}
 
+void CALEClientSetScanFlag(bool flag)
+{
+    ca_mutex_lock(g_scanMutex);
+    g_isStartedScan = flag;
+    ca_mutex_unlock(g_scanMutex);
 }
 
-void CANativeLEStopScanImpl(JNIEnv *env, jobject callback)
+CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback)
 {
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeLEStopScan");
+    OIC_LOG(DEBUG, TAG, "CALEClientStopScanImpl");
+    VERIFY_NON_NULL(callback, TAG, "callback is null");
+    VERIFY_NON_NULL(env, TAG, "env is null");
 
-    if(!CANativeIsEnableBTAdapter(env))
+    if (!CALEIsEnableBTAdapter(env))
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] BT adpater is not enable");
-        return;
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return CA_ADAPTER_NOT_ENABLED;
     }
 
     // get default bt adapter class
-    jclass jni_cid_BTAdapter = (*env)->FindClass(env,  CLASSPATH_BT_ADPATER);
-    if(!jni_cid_BTAdapter)
+    jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
+    if (!jni_cid_BTAdapter)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] getState From BTAdapter: jni_cid_BTAdapter is null");
-        return;
+        OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
+        return CA_STATUS_FAILED;
     }
 
     // get remote bt adapter method
-    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, "[BLE][Native] getState From BTAdapter: jni_mid_getDefaultAdapter is null");
-        return;
+        OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
+        return CA_STATUS_FAILED;
     }
 
     // get start le scan method
     jmethodID jni_mid_stopLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "stopLeScan",
-            "(Landroid/bluetooth/BluetoothAdapter$LeScanCallback;)V");
-    if(!jni_mid_stopLeScan)
+                                                       "(Landroid/bluetooth/"
+                                                       "BluetoothAdapter$LeScanCallback;)V");
+    if (!jni_mid_stopLeScan)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] stopLeScan: jni_mid_stopLeScan is null");
-        return;
+        OIC_LOG(ERROR, TAG, "stopLeScan: jni_mid_stopLeScan is null");
+        return CA_STATUS_FAILED;
     }
 
     // gat bt adapter object
-    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, "[BLE][Native] jni_obj_BTAdapter is null");
-        return;
+        OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
+        return CA_STATUS_FAILED;
     }
 
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - request to stop LE Scan");
+    OIC_LOG(DEBUG, TAG, "CALL API - request to stop LE Scan");
     // call start le scan method
     (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_stopLeScan, callback);
+    if ((*env)->ExceptionCheck(env))
+    {
+        OIC_LOG(ERROR, TAG, "stopLeScan has failed");
+        (*env)->ExceptionDescribe(env);
+        (*env)->ExceptionClear(env);
+        return CA_STATUS_FAILED;
+    }
+
+    return CA_STATUS_OK;
 }
 
-int32_t CANativeLEConnect(JNIEnv *env, jobject bluetoothDevice, jobject context,
-        jboolean autoconnect, jobject callback)
+void CALEClientSetAutoConnectFlag(jboolean flag)
 {
-    if(!CANativeIsEnableBTAdapter(env))
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] BT adpater is not enable");
-        return 0;
-    }
+    OIC_LOG_V(INFO, TAG, "auto connect flag is set %d", flag);
+    g_autoConnectFlag = flag;
+}
 
-    jstring jni_address = CANativeGetAddressFromBTDevice(env, bluetoothDevice);
-    const char * addr = (*env)->GetStringUTFChars(env, jni_address, NULL);
-    OIC_LOG_V(DEBUG, TAG, "[BLE][Native] request connectGatt to %s", addr);
+jboolean CALEClientGetAutoConnectFlag()
+{
+    OIC_LOG_V(INFO, TAG, "auto connect flag is %d", g_autoConnectFlag);
+    return g_autoConnectFlag;
+}
 
-    // GATT CONNECT
+jobject CALEClientConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
+{
+    OIC_LOG(DEBUG, TAG, "CALEClientConnect");
+    VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
+    VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
 
-    // get BluetoothDevice class
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] get BluetoothDevice class");
-    jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, "android/bluetooth/BluetoothDevice");
-    if(!jni_cid_BluetoothDevice)
+    // get gatt object from Bluetooth Device object for closeProfileProxy(..)
+    jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, bluetoothDevice);
+    if (jni_address)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] bleConnect: jni_cid_BluetoothDevice is null");
-        return 0;
-    }
+        const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+        if (!address)
+        {
+            OIC_LOG(ERROR, TAG, "address is not available");
+            return NULL;
+        }
 
-    // get connectGatt method
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] get connectGatt method");
-    jmethodID jni_mid_connectGatt = (*env)->GetMethodID(env, jni_cid_BluetoothDevice,
-            "connectGatt",
-            "(Landroid/content/Context;ZLandroid/bluetooth/BluetoothGattCallback;)Landroid/bluetooth/BluetoothGatt;");
-    if(!jni_mid_connectGatt)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] bleConnect: jni_mid_connectGatt is null");
-        return 0;
+        // close the gatt service
+        jobject gatt = CALEClientGetGattObjInList(env, address);
+        if (gatt)
+        {
+            CAResult_t res = CALEClientCloseProfileProxy(env, gatt);
+            if (CA_STATUS_OK != res)
+            {
+                OIC_LOG(ERROR, TAG, "CALEClientCloseProfileProxy has failed");
+                (*env)->ReleaseStringUTFChars(env, jni_address, address);
+                return NULL;
+            }
+
+            // clean previous gatt object after close profile service
+            res = CALEClientRemoveGattObjForAddr(env, jni_address);
+            if (CA_STATUS_OK != res)
+            {
+                OIC_LOG(ERROR, TAG, "CALEClientRemoveGattObjForAddr has failed");
+                (*env)->ReleaseStringUTFChars(env, jni_address, address);
+                return NULL;
+            }
+        }
+        (*env)->ReleaseStringUTFChars(env, jni_address, address);
     }
 
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] Call object method - connectGatt");
-    jobject jni_obj_connectGatt = (*env)->CallObjectMethod(env, bluetoothDevice,
-            jni_mid_connectGatt, NULL, autoconnect, callback);
-    if(!jni_obj_connectGatt)
+    jobject newGatt = CALEClientGattConnect(env, bluetoothDevice, autoconnect);
+    if (!newGatt)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - connectGatt was failed.obj will be removed");
-        CANativeRemoveDevice(env, jni_address);
-        CANativeupdateSendCnt(env);
-        return -1;
+        OIC_LOG(DEBUG, TAG, "re-connection will be started");
+        return NULL;
     }
-    else
+
+    // add new gatt object into g_gattObjectList
+    CAResult_t res = CALEClientAddGattobjToList(env, newGatt);
+    if (CA_STATUS_OK != res)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - connecting..");
+        OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
+        return NULL;
     }
-    return 1;
+
+    return newGatt;
 }
 
-void CANativeLEDisconnect(JNIEnv *env, jobject bluetoothGatt)
+jobject CALEClientGattConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
 {
-    if(!CANativeIsEnableBTAdapter(env))
+    OIC_LOG(DEBUG, TAG, "GATT CONNECT");
+    VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
+    VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
+
+    if (!CALEIsEnableBTAdapter(env))
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] BT adpater is not enable");
-        return;
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return NULL;
     }
 
-    // GATT DISCONNECT
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] GATT DISCONNECT");
-
-    // get BluetoothGatt class
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] get BluetoothGatt classjobject bluetoothGatt");
+    jstring jni_address = CALEGetAddressFromBTDevice(env, bluetoothDevice);
+    if (!jni_address)
+    {
+        OIC_LOG(ERROR, TAG, "bleConnect: CALEGetAddressFromBTDevice is null");
+        return NULL;
+    }
+
+    // get BluetoothDevice class
+    OIC_LOG(DEBUG, TAG, "get BluetoothDevice class");
+    jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, "android/bluetooth/BluetoothDevice");
+    if (!jni_cid_BluetoothDevice)
+    {
+        OIC_LOG(ERROR, TAG, "bleConnect: jni_cid_BluetoothDevice is null");
+        return NULL;
+    }
+
+    // get connectGatt method
+    OIC_LOG(DEBUG, TAG, "get connectGatt method");
+    jmethodID jni_mid_connectGatt = (*env)->GetMethodID(env, jni_cid_BluetoothDevice, "connectGatt",
+                                                        "(Landroid/content/Context;ZLandroid/"
+                                                        "bluetooth/BluetoothGattCallback;)"
+                                                        "Landroid/bluetooth/BluetoothGatt;");
+    if (!jni_mid_connectGatt)
+    {
+        OIC_LOG(ERROR, TAG, "bleConnect: jni_mid_connectGatt is null");
+        return NULL;
+    }
+
+    OIC_LOG(INFO, TAG, "CALL API - connectGatt");
+    jobject jni_obj_connectGatt = (*env)->CallObjectMethod(env, bluetoothDevice,
+                                                           jni_mid_connectGatt,
+                                                           NULL,
+                                                           autoconnect, g_leGattCallback);
+    if (!jni_obj_connectGatt)
+    {
+        OIC_LOG(ERROR, TAG, "connectGatt was failed..it will be removed");
+        CALEClientRemoveDeviceInScanDeviceList(env, jni_address);
+        CALEClientUpdateSendCnt(env);
+        return NULL;
+    }
+    else
+    {
+        OIC_LOG(DEBUG, TAG, "le connecting..please wait..");
+    }
+    return jni_obj_connectGatt;
+}
+
+CAResult_t CALEClientCloseProfileProxy(JNIEnv *env, jobject gatt)
+{
+    OIC_LOG(DEBUG, TAG, "IN - CALEClientCloseProfileProxy");
+
+    VERIFY_NON_NULL(env, TAG, "env is null");
+    VERIFY_NON_NULL(gatt, TAG, "gatt is null");
+
+    jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
+    if (!jni_cid_BTAdapter)
+    {
+        OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
+        return CA_STATUS_FAILED;
+    }
+
+    // get remote bt adapter method
+    jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
+                                                                    "getDefaultAdapter",
+                                                                    METHODID_OBJECTNONPARAM);
+    if (!jni_mid_getDefaultAdapter)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
+        return CA_STATUS_FAILED;
+    }
+
+    // gat bt adapter object
+    jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
+                                                               jni_mid_getDefaultAdapter);
+    if (!jni_obj_BTAdapter)
+    {
+        OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
+        return CA_STATUS_FAILED;
+    }
+
+    // get closeProfileProxy method
+    jmethodID jni_mid_closeProfileProxy = (*env)->GetMethodID(env, jni_cid_BTAdapter,
+                                                              "closeProfileProxy",
+                                                              "(ILandroid/bluetooth/"
+                                                              "BluetoothProfile;)V");
+    if (!jni_mid_closeProfileProxy)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_closeProfileProxy is null");
+        return CA_STATUS_FAILED;
+    }
+
+    jclass jni_cid_BTProfile = (*env)->FindClass(env, CLASSPATH_BT_PROFILE);
+    if (!jni_cid_BTProfile)
+    {
+        OIC_LOG(ERROR, TAG, "jni_cid_BTProfile is null");
+        return CA_STATUS_FAILED;
+    }
+
+    // GATT - Constant value : 7 (0x00000007)
+    jfieldID id_gatt = (*env)->GetStaticFieldID(env, jni_cid_BTProfile,
+                                                "GATT", "I");
+    if (!id_gatt)
+    {
+        OIC_LOG(ERROR, TAG, "id_gatt is null");
+        return CA_STATUS_FAILED;
+    }
+
+    jint jni_gatt = (*env)->GetStaticIntField(env, jni_cid_BTProfile, id_gatt);
+
+    OIC_LOG(DEBUG, TAG, "CALL API - close the connection of the profile proxy to the Service");
+    (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_closeProfileProxy, jni_gatt, gatt);
+    if ((*env)->ExceptionCheck(env))
+    {
+        OIC_LOG(ERROR, TAG, "closeProfileProxy has failed");
+        (*env)->ExceptionDescribe(env);
+        (*env)->ExceptionClear(env);
+        return CA_STATUS_FAILED;
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT - CALEClientCloseProfileProxy");
+    return CA_STATUS_OK;
+}
+
+
+CAResult_t CALEClientDisconnect(JNIEnv *env, jobject bluetoothGatt)
+{
+    OIC_LOG(DEBUG, TAG, "GATT DISCONNECT");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+    VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
+
+    // get BluetoothGatt class
     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
-    if(!jni_cid_BluetoothGatt)
+    if (!jni_cid_BluetoothGatt)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_cid_BluetoothGatt is null");
-        return;
+        OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
+        return CA_STATUS_FAILED;
     }
 
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] get gatt disconnect method");
+    OIC_LOG(DEBUG, TAG, "get gatt disconnect method");
     jmethodID jni_mid_disconnectGatt = (*env)->GetMethodID(env, jni_cid_BluetoothGatt,
-            "disconnect","()V");
-    if(!jni_mid_disconnectGatt)
+                                                           "disconnect", "()V");
+    if (!jni_mid_disconnectGatt)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_mid_disconnectGatt is null");
-        return;
+        OIC_LOG(ERROR, TAG, "jni_mid_disconnectGatt is null");
+        return CA_STATUS_FAILED;
     }
 
     // call disconnect gatt method
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - request disconnectGatt");
+    OIC_LOG(DEBUG, TAG, "CALL API - request disconnect gatt");
     (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_disconnectGatt);
+    if ((*env)->ExceptionCheck(env))
+    {
+        OIC_LOG(ERROR, TAG, "disconnect has failed");
+        (*env)->ExceptionDescribe(env);
+        (*env)->ExceptionClear(env);
+        return CA_STATUS_FAILED;
+    }
 
+    OIC_LOG(DEBUG, TAG, "disconnecting Gatt...");
+
+    return CA_STATUS_OK;
 }
 
-void CANativeLEDiscoverServices(JNIEnv *env, jobject bluetoothGatt)
+CAResult_t CALEClientDisconnectAll(JNIEnv *env)
 {
-    if(!CANativeIsEnableBTAdapter(env))
+    OIC_LOG(DEBUG, TAG, "CALEClientDisconnectAll");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+
+    if (!g_gattObjectList)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] BT adpater is not enable");
-        return;
+        OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
+        return CA_STATUS_OK;
     }
 
-    // GATT SERVICE DISCOVERY
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] GATT SERVICE DISCOVERY");
+    uint32_t length = u_arraylist_length(g_gattObjectList);
+    OIC_LOG_V(DEBUG, TAG, "list length : %d", length);
+    for (uint32_t index = 0; index < length; index++)
+    {
+        OIC_LOG(DEBUG, TAG, "start CALEClientDisconnectAll");
+        jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
+        if (!jarrayObj)
+        {
+            OIC_LOG(ERROR, TAG, "jarrayObj is null");
+            continue;
+        }
+        CAResult_t res = CALEClientDisconnect(env, jarrayObj);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
+            continue;
+        }
+    }
+
+    return CA_STATUS_OK;
+}
+
+CAResult_t CALEClientDisconnectforAddress(JNIEnv *env, jstring remote_address)
+{
+    OIC_LOG(DEBUG, TAG, "IN-CALEClientDisconnectforAddress");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+
+    if (!g_gattObjectList)
+    {
+        OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
+        return CA_STATUS_OK;
+    }
+
+    char* address = (char*)(*env)->GetStringUTFChars(env, remote_address, NULL);
+    if (!address)
+    {
+        OIC_LOG(ERROR, TAG, "address is null");
+        return CA_STATUS_FAILED;
+    }
+
+    uint32_t length = u_arraylist_length(g_gattObjectList);
+    for (uint32_t index = 0; index < length; index++)
+    {
+        jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
+        if (!jarrayObj)
+        {
+            OIC_LOG(ERROR, TAG, "jarrayObj is null");
+            continue;
+        }
+
+        jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
+        if (!jni_setAddress)
+        {
+            OIC_LOG(ERROR, TAG, "jni_setAddress is null");
+            (*env)->ReleaseStringUTFChars(env, remote_address, address);
+            return CA_STATUS_FAILED;
+        }
+
+        const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
+        if (!setAddress)
+        {
+            OIC_LOG(ERROR, TAG, "setAddress is null");
+            (*env)->ReleaseStringUTFChars(env, remote_address, address);
+            return CA_STATUS_FAILED;
+        }
+
+        OIC_LOG_V(DEBUG, TAG, "target address : %s, set address : %s", address, setAddress);
+        if (!strcmp(address, setAddress))
+        {
+            CAResult_t res = CALEClientDisconnect(env, jarrayObj);
+            if (CA_STATUS_OK != res)
+            {
+                OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
+                (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+                (*env)->ReleaseStringUTFChars(env, remote_address, address);
+                return CA_STATUS_FAILED;
+            }
+            (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+            (*env)->ReleaseStringUTFChars(env, remote_address, address);
+            return CA_STATUS_OK;
+        }
+        (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+    }
+    (*env)->ReleaseStringUTFChars(env, remote_address, address);
+
+    OIC_LOG(DEBUG, TAG, "OUT-CALEClientDisconnectforAddress");
+    return CA_STATUS_OK;
+}
+
+CAResult_t CALEClientDiscoverServices(JNIEnv *env, jobject bluetoothGatt)
+{
+    VERIFY_NON_NULL(env, TAG, "env is null");
+    VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
+
+    if (!CALEIsEnableBTAdapter(env))
+    {
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return CA_ADAPTER_NOT_ENABLED;
+    }
 
     // get BluetoothGatt class
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] get BluetoothGatt class");
+    OIC_LOG(DEBUG, TAG, "get BluetoothGatt class");
     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
-    if(!jni_cid_BluetoothGatt)
+    if (!jni_cid_BluetoothGatt)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_cid_BluetoothGatt is null");
-        return;
+        OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
+        return CA_STATUS_FAILED;
     }
 
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] discovery gatt services method");
+    OIC_LOG(DEBUG, TAG, "discovery gatt services method");
     jmethodID jni_mid_discoverServices = (*env)->GetMethodID(env, jni_cid_BluetoothGatt,
-            "discoverServices","()Z");
-    if(!jni_mid_discoverServices)
+                                                             "discoverServices", "()Z");
+    if (!jni_mid_discoverServices)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_mid_discoverServices is null");
-        return;
+        OIC_LOG(ERROR, TAG, "jni_mid_discoverServices is null");
+        return CA_STATUS_FAILED;
     }
     // call disconnect gatt method
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - request discovery gatt services");
-    (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_discoverServices);
+    OIC_LOG(DEBUG, TAG, "CALL API - request discovery gatt services");
+    jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_discoverServices);
+    if (!ret)
+    {
+        OIC_LOG(ERROR, TAG, "discoverServices has not been started");
+        return CA_STATUS_FAILED;
+    }
+
+    return CA_STATUS_OK;
+}
+
+static void CALEWriteCharacteristicThread(void* object)
+{
+    VERIFY_NON_NULL_VOID(object, TAG, "object is null");
+
+    bool isAttached = false;
+    JNIEnv* env;
+    jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
+    if (JNI_OK != res)
+    {
+        OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
+        res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
+
+        if (JNI_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
+            return;
+        }
+        isAttached = true;
+    }
+
+    jobject gatt = (jobject)object;
+    CAResult_t ret = CALESetValueAndWriteCharacteristic(env, gatt);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CALESetValueAndWriteCharacteristic has failed");
+    }
+
+    if (isAttached)
+    {
+        (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
+}
+
+CAResult_t CALESetValueAndWriteCharacteristic(JNIEnv* env, jobject gatt)
+{
+    VERIFY_NON_NULL(gatt, TAG, "gatt is null");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+
+    // send data
+    jobject jni_obj_character = CALEClientCreateGattCharacteristic(env, gatt, g_sendBuffer);
+    if (!jni_obj_character)
+    {
+        CALEClientSendFinish(env, gatt);
+        return CA_STATUS_FAILED;
+    }
+
+    CAResult_t ret = CALEClientWriteCharacteristicImpl(env, gatt, jni_obj_character);
+    if (CA_STATUS_OK != ret)
+    {
+        CALEClientSendFinish(env, gatt);
+        return CA_STATUS_FAILED;
+    }
+
+    // wait for callback for write Characteristic with success to sent data
+    OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
+    ca_mutex_lock(g_threadWriteCharacteristicMutex);
+    if (!g_isSignalSetFlag)
+    {
+        OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success");
+        if (CA_WAIT_SUCCESS != ca_cond_wait_for(g_threadWriteCharacteristicCond,
+                                  g_threadWriteCharacteristicMutex,
+                                  WAIT_TIME_WRITE_CHARACTERISTIC))
+        {
+            OIC_LOG(ERROR, TAG, "there is no response. write has failed");
+            g_isSignalSetFlag = false;
+            ca_mutex_unlock(g_threadWriteCharacteristicMutex);
+            return CA_STATUS_FAILED;
+        }
+    }
+    // reset flag set by writeCharacteristic Callback
+    g_isSignalSetFlag = false;
+    ca_mutex_unlock(g_threadWriteCharacteristicMutex);
+
+    OIC_LOG(INFO, TAG, "writeCharacteristic success!!");
+    return CA_STATUS_OK;
 }
 
-jboolean CANativeLESendData(JNIEnv *env, jobject bluetoothGatt, jobject gattCharacteristic)
+CAResult_t CALEClientWriteCharacteristic(JNIEnv *env, jobject gatt)
 {
-    if(!CANativeIsEnableBTAdapter(env))
+    OIC_LOG(DEBUG, TAG, "IN - CALEClientWriteCharacteristic");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+    VERIFY_NON_NULL(gatt, TAG, "gatt is null");
+
+    jobject gattParam = (*env)->NewGlobalRef(env, gatt);
+    if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle,
+                                                CALEWriteCharacteristicThread, (void*)gattParam))
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] BT adpater is not enable");
-        return FALSE;
+        OIC_LOG(ERROR, TAG, "Failed to create read thread!");
+        return CA_STATUS_FAILED;
     }
 
-    // WRITE GATT CHARACTERISTIC
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] WRITE GATT CHARACTERISTIC");
+    OIC_LOG(DEBUG, TAG, "OUT - CALEClientWriteCharacteristic");
+    return CA_STATUS_OK;
+}
+
+CAResult_t CALEClientWriteCharacteristicImpl(JNIEnv *env, jobject bluetoothGatt,
+                                             jobject gattCharacteristic)
+{
+    OIC_LOG(DEBUG, TAG, "WRITE GATT CHARACTERISTIC");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+    VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
+    VERIFY_NON_NULL(gattCharacteristic, TAG, "gattCharacteristic is null");
+
+    if (!CALEIsEnableBTAdapter(env))
+    {
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return CA_STATUS_FAILED;
+    }
 
     // get BluetoothGatt class
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] get BluetoothGatt class");
+    OIC_LOG(DEBUG, TAG, "get BluetoothGatt class");
     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
-    if(!jni_cid_BluetoothGatt)
+    if (!jni_cid_BluetoothGatt)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_cid_BluetoothGatt is null");
-        return FALSE;
+        OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
+        return CA_STATUS_FAILED;
     }
 
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] write characteristic method");
+    OIC_LOG(DEBUG, TAG, "write characteristic method");
     jmethodID jni_mid_writeCharacteristic = (*env)->GetMethodID(env, jni_cid_BluetoothGatt,
-            "writeCharacteristic", "(Landroid/bluetooth/BluetoothGattCharacteristic;)Z");
-    if(!jni_mid_writeCharacteristic)
+                                                                "writeCharacteristic",
+                                                                "(Landroid/bluetooth/"
+                                                                "BluetoothGattCharacteristic;)Z");
+    if (!jni_mid_writeCharacteristic)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_mid_writeCharacteristic is null");
-        return FALSE;
+        OIC_LOG(ERROR, TAG, "jni_mid_writeCharacteristic is null");
+        return CA_STATUS_FAILED;
     }
 
     // call disconnect gatt method
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - request to write gatt characteristic");
-    jboolean ret = (jboolean)(*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_writeCharacteristic, gattCharacteristic);
-    if(ret)
+    OIC_LOG(DEBUG, TAG, "CALL API - request to write gatt characteristic");
+    jboolean ret = (jboolean)(*env)->CallBooleanMethod(env, bluetoothGatt,
+                                                       jni_mid_writeCharacteristic,
+                                                       gattCharacteristic);
+    if (ret)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] writeCharacteristic is success");
+        OIC_LOG(DEBUG, TAG, "writeCharacteristic is called successfully");
     }
     else
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] writeCharacteristic is failed");
-        return FALSE;
+        OIC_LOG(ERROR, TAG, "writeCharacteristic has failed");
+        return CA_STATUS_FAILED;
     }
-    return TRUE;
+
+    return CA_STATUS_OK;
 }
 
-void CANativeReadCharacteristic(JNIEnv *env, jobject bluetoothGatt)
+CAResult_t CALEClientReadCharacteristic(JNIEnv *env, jobject bluetoothGatt)
 {
+    VERIFY_NON_NULL(env, TAG, "env is null");
+    VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
 
-   if(!CANativeIsEnableBTAdapter(env))
-   {
-       OIC_LOG(DEBUG, TAG, "[BLE][Native] BT adpater is not enable");
-       return;
-   }
+    if (!CALEIsEnableBTAdapter(env))
+    {
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return CA_STATUS_FAILED;
+    }
+
+    jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
+    if (!jni_cid_BluetoothGatt)
+    {
+        OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
+        return CA_STATUS_FAILED;
+    }
+
+    jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
+    if (!jni_uuid)
+    {
+        OIC_LOG(ERROR, TAG, "jni_uuid is null");
+        return CA_STATUS_FAILED;
+    }
 
-   jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
-   if(!jni_cid_BluetoothGatt)
-   {
-       OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_cid_BluetoothGatt is null");
-       return;
-   }
+    jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
+    if (!jni_obj_GattCharacteristic)
+    {
+        OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
+        return CA_STATUS_FAILED;
+    }
 
-   jstring jni_uuid = (*env)->NewStringUTF(env, IOTIVITY_GATT_RX_UUID);
-   jobject jni_obj_GattCharacteristic = CANativeGetGattService(env, bluetoothGatt, jni_uuid);
-   if(!jni_obj_GattCharacteristic)
-   {
-       OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_obj_GattCharacteristic is null");
-       return;
-   }
+    OIC_LOG(DEBUG, TAG, "read characteristic method");
+    jmethodID jni_mid_readCharacteristic = (*env)->GetMethodID(env, jni_cid_BluetoothGatt,
+                                                               "readCharacteristic",
+                                                               "(Landroid/bluetooth/"
+                                                               "BluetoothGattCharacteristic;)Z");
+    if (!jni_mid_readCharacteristic)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_readCharacteristic is null");
+        return CA_STATUS_FAILED;
+    }
 
-   OIC_LOG(DEBUG, TAG, "[BLE][Native] read characteristic method");
-   jmethodID jni_mid_readCharacteristic = (*env)->GetMethodID(env, jni_cid_BluetoothGatt, "readCharacteristic", "(Landroid/bluetooth/BluetoothGattCharacteristic;)Z");
-   if(!jni_mid_readCharacteristic)
-   {
-       OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_mid_readCharacteristic is null");
-       return;
-   }
+    // call disconnect gatt method
+    OIC_LOG(DEBUG, TAG, "CALL API - request to read gatt characteristic");
+    jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_readCharacteristic,
+                                             jni_obj_GattCharacteristic);
+    if (ret)
+    {
+        OIC_LOG(DEBUG, TAG, "readCharacteristic success");
+    }
+    else
+    {
+        OIC_LOG(ERROR, TAG, "readCharacteristic has failed");
+        return CA_STATUS_FAILED;
+    }
 
-   // call disconnect gatt method
-   OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - request to read gatt characteristic");
-   jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_readCharacteristic, jni_obj_GattCharacteristic);
-   if(ret)
-   {
-       OIC_LOG(DEBUG, TAG, "[BLE][Native] readCharacteristic is success");
-   }
-   else
-   {
-       OIC_LOG(DEBUG, TAG, "[BLE][Native] readCharacteristic is failed");
-   }
+    return CA_STATUS_OK;
 }
 
-jboolean CANativeSetCharacteristicNoti(JNIEnv *env, jobject bluetoothGatt, const char* uuid)
+CAResult_t CALEClientSetCharacteristicNotification(JNIEnv *env, jobject bluetoothGatt,
+                                                   jobject characteristic)
 {
-    if(!CANativeIsEnableBTAdapter(env))
+    VERIFY_NON_NULL(env, TAG, "env is null");
+    VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
+    VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
+
+    if (!CALEIsEnableBTAdapter(env))
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] BT adpater is not enable");
-        return FALSE;
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return CA_ADAPTER_NOT_ENABLED;
     }
 
     // get BluetoothGatt class
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeSetCharacteristicNoti");
+    OIC_LOG(DEBUG, TAG, "CALEClientSetCharacteristicNotification");
     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
-    if(!jni_cid_BluetoothGatt)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_cid_BluetoothGatt is null");
-        return FALSE;
-    }
-
-    jstring jni_uuid = (*env)->NewStringUTF(env, uuid);
-    jobject jni_obj_GattCharacteristic = CANativeGetGattService(env, bluetoothGatt, jni_uuid);
-    if(!jni_obj_GattCharacteristic)
+    if (!jni_cid_BluetoothGatt)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_obj_GattCharacteristic is null");
-        return FALSE;
+        OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
+        return CA_STATUS_FAILED;
     }
 
     // set Characteristic Notification
-    jmethodID jni_mid_setNotification = (*env)->GetMethodID(env, jni_cid_BluetoothGatt, "setCharacteristicNotification",
-            "(Landroid/bluetooth/BluetoothGattCharacteristic;Z)Z");
-    if(!jni_mid_setNotification)
+    jmethodID jni_mid_setNotification = (*env)->GetMethodID(env, jni_cid_BluetoothGatt,
+                                                            "setCharacteristicNotification",
+                                                            "(Landroid/bluetooth/"
+                                                            "BluetoothGattCharacteristic;Z)Z");
+    if (!jni_mid_setNotification)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_mid_getService is null");
-        return FALSE;
+        OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
+        return CA_STATUS_FAILED;
     }
 
-    jboolean enable = TRUE;
-    jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_setNotification, jni_obj_GattCharacteristic, enable);
-    if(1 == ret)
+    jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_setNotification,
+                                             characteristic, JNI_TRUE);
+    if (JNI_TRUE == ret)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - setCharacteristicNotification is success");
-        return TRUE;
+        OIC_LOG(DEBUG, TAG, "CALL API - setCharacteristicNotification success");
     }
     else
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - setCharacteristicNotification is failed");
-        return FALSE;
+        OIC_LOG(ERROR, TAG, "CALL API - setCharacteristicNotification has failed");
+        return CA_STATUS_FAILED;
     }
+
+    return CA_STATUS_OK;
 }
 
-jobject CANativeGetGattService(JNIEnv *env, jobject bluetoothGatt, jstring characterUUID)
+jobject CALEClientGetGattService(JNIEnv *env, jobject bluetoothGatt, jstring characterUUID)
 {
-    if(!CANativeIsEnableBTAdapter(env))
+    VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
+    VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
+    VERIFY_NON_NULL_RET(characterUUID, TAG, "characterUUID is null", NULL);
+
+    if (!CALEIsEnableBTAdapter(env))
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] BT adpater is not enable");
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
         return NULL;
     }
 
     // get BluetoothGatt class
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeGetGattService");
+    OIC_LOG(DEBUG, TAG, "CALEClientGetGattService");
     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
-    if(!jni_cid_BluetoothGatt)
+    if (!jni_cid_BluetoothGatt)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_cid_BluetoothGatt is null");
+        OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
         return NULL;
     }
 
-    jmethodID jni_mid_getService = (*env)->GetMethodID(env, jni_cid_BluetoothGatt, "getService",
+    jmethodID jni_mid_getService = (*env)->GetMethodID(
+            env, jni_cid_BluetoothGatt, "getService",
             "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothGattService;");
-    if(!jni_mid_getService)
+    if (!jni_mid_getService)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_mid_getService is null");
+        OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
         return NULL;
     }
 
-    jobject jni_obj_service_uuid = CANativeGetUUIDObject(env, IOTIVITY_GATT_SERVIE_UUID);
-    if(!jni_obj_service_uuid)
+    jobject jni_obj_service_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
+    if (!jni_obj_service_uuid)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_obj_service_uuid is null");
+        OIC_LOG(ERROR, TAG, "jni_obj_service_uuid is null");
         return NULL;
     }
 
     // get bluetooth gatt service
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] request to get service");
-    jobject jni_obj_gattService = (*env)->CallObjectMethod(env, bluetoothGatt, jni_mid_getService, jni_obj_service_uuid);
+    OIC_LOG(DEBUG, TAG, "request to get service");
+    jobject jni_obj_gattService = (*env)->CallObjectMethod(env, bluetoothGatt, jni_mid_getService,
+                                                           jni_obj_service_uuid);
+    if (!jni_obj_gattService)
+    {
+        OIC_LOG(ERROR, TAG, "jni_obj_gattService is null");
+        return NULL;
+    }
 
     // get bluetooth gatt service class
-    jclass jni_cid_BluetoothGattService = (*env)->FindClass(env, "android/bluetooth/BluetoothGattService");
-    if(!jni_cid_BluetoothGattService)
+    jclass jni_cid_BluetoothGattService = (*env)->FindClass(
+            env, "android/bluetooth/BluetoothGattService");
+    if (!jni_cid_BluetoothGattService)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_cid_BluetoothGattService is null");
+        OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGattService is null");
         return NULL;
     }
 
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] get gatt getCharacteristic method");
-    jmethodID jni_mid_getCharacteristic = (*env)->GetMethodID(env, jni_cid_BluetoothGattService, "getCharacteristic",
-            "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothGattCharacteristic;");
-    if(!jni_mid_getCharacteristic)
+    OIC_LOG(DEBUG, TAG, "get gatt getCharacteristic method");
+    jmethodID jni_mid_getCharacteristic = (*env)->GetMethodID(env, jni_cid_BluetoothGattService,
+                                                              "getCharacteristic",
+                                                              "(Ljava/util/UUID;)"
+                                                              "Landroid/bluetooth/"
+                                                              "BluetoothGattCharacteristic;");
+    if (!jni_mid_getCharacteristic)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_mid_getCharacteristic is null");
+        OIC_LOG(ERROR, TAG, "jni_mid_getCharacteristic is null");
         return NULL;
     }
 
     const char* uuid = (*env)->GetStringUTFChars(env, characterUUID, NULL);
-    jobject jni_obj_tx_uuid = CANativeGetUUIDObject(env, uuid);
-    if(!jni_obj_tx_uuid)
+    if (!uuid)
+    {
+        OIC_LOG(ERROR, TAG, "uuid is null");
+        return NULL;
+    }
+
+    jobject jni_obj_tx_uuid = CALEClientGetUUIDObject(env, uuid);
+    if (!jni_obj_tx_uuid)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_obj_tx_uuid is null");
+        OIC_LOG(ERROR, TAG, "jni_obj_tx_uuid is null");
+        (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
         return NULL;
     }
 
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] request to get Characteristic");
-    jobject jni_obj_GattCharacteristic = (*env)->CallObjectMethod(env, jni_obj_gattService, jni_mid_getCharacteristic, jni_obj_tx_uuid);
+    OIC_LOG(DEBUG, TAG, "request to get Characteristic");
+    jobject jni_obj_GattCharacteristic = (*env)->CallObjectMethod(env, jni_obj_gattService,
+                                                                  jni_mid_getCharacteristic,
+                                                                  jni_obj_tx_uuid);
 
+    (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
     return jni_obj_GattCharacteristic;
 }
 
-jobject CANativeCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, jbyteArray data)
+jobject CALEClientCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, jbyteArray data)
 {
-    if(!CANativeIsEnableBTAdapter(env))
+    OIC_LOG(DEBUG, TAG, "CALEClientCreateGattCharacteristic");
+    VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
+    VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
+    VERIFY_NON_NULL_RET(data, TAG, "data is null", NULL);
+
+    if (!CALEIsEnableBTAdapter(env))
+    {
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return NULL;
+    }
+
+    jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_REQUEST_UUID);
+    if (!jni_uuid)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] BT adpater is not enable");
+        OIC_LOG(ERROR, TAG, "jni_uuid is null");
         return NULL;
     }
 
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeCreateGattCharacteristic");
-    jstring jni_uuid = (*env)->NewStringUTF(env, IOTIVITY_GATT_TX_UUID);
-    jobject jni_obj_GattCharacteristic = CANativeGetGattService(env, bluetoothGatt, jni_uuid);
-    if(!jni_obj_GattCharacteristic)
+    jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
+    if (!jni_obj_GattCharacteristic)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_obj_GattCharacteristic is null");
+        OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
         return NULL;
     }
 
-    jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(env, "android/bluetooth/BluetoothGattCharacteristic");
-    if(!jni_cid_BTGattCharacteristic)
+    jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(env, "android/bluetooth"
+                                                            "/BluetoothGattCharacteristic");
+    if (!jni_cid_BTGattCharacteristic)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_cid_BTGattCharacteristic is null");
+        OIC_LOG(ERROR, TAG, "jni_cid_BTGattCharacteristic is null");
         return NULL;
     }
 
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] set value in Characteristic");
+    OIC_LOG(DEBUG, TAG, "set value in Characteristic");
     jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic, "setValue",
-            "([B)Z");
-    if(!jni_mid_setValue)
+                                                     "([B)Z");
+    if (!jni_mid_setValue)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_mid_setValue is null");
+        OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
         return NULL;
     }
 
-    jboolean ret = (*env)->CallBooleanMethod(env, jni_obj_GattCharacteristic, jni_mid_setValue, data);
-    if(1 == ret)
+    jboolean ret = (*env)->CallBooleanMethod(env, jni_obj_GattCharacteristic, jni_mid_setValue,
+                                             data);
+    if (JNI_TRUE == ret)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] the locally stored value has been set");
-        return jni_obj_GattCharacteristic;
+        OIC_LOG(DEBUG, TAG, "the locally stored value has been set");
     }
     else
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] the locally stored value hasn't been set");
+        OIC_LOG(ERROR, TAG, "the locally stored value hasn't been set");
+        return NULL;
+    }
+
+    // set Write Type
+    jmethodID jni_mid_setWriteType = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic,
+                                                         "setWriteType", "(I)V");
+    if (!jni_mid_setWriteType)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_setWriteType is null");
+        return NULL;
+    }
+
+    jfieldID jni_fid_no_response = (*env)->GetStaticFieldID(env, jni_cid_BTGattCharacteristic,
+                                                            "WRITE_TYPE_NO_RESPONSE", "I");
+    if (!jni_fid_no_response)
+    {
+        OIC_LOG(ERROR, TAG, "jni_fid_no_response is not available");
         return NULL;
     }
+
+    jint jni_int_val = (*env)->GetStaticIntField(env, jni_cid_BTGattCharacteristic,
+                                                 jni_fid_no_response);
+
+    (*env)->CallVoidMethod(env, jni_obj_GattCharacteristic, jni_mid_setWriteType, jni_int_val);
+
+    return jni_obj_GattCharacteristic;
 }
 
-jbyteArray CANativeGetValueFromCharacteristic(JNIEnv *env, jobject characteristic)
+jbyteArray CALEClientGetValueFromCharacteristic(JNIEnv *env, jobject characteristic)
 {
-    if(!CANativeIsEnableBTAdapter(env))
+    VERIFY_NON_NULL_RET(characteristic, TAG, "characteristic is null", NULL);
+    VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
+
+    if (!CALEIsEnableBTAdapter(env))
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] BT adpater is not enable");
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
         return NULL;
     }
 
-    jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(env, "android/bluetooth/BluetoothGattCharacteristic");
-    if(!jni_cid_BTGattCharacteristic)
+    jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(env, "android/bluetooth/"
+                                                            "BluetoothGattCharacteristic");
+    if (!jni_cid_BTGattCharacteristic)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_cid_BTGattCharacteristic is null");
+        OIC_LOG(ERROR, TAG, "jni_cid_BTGattCharacteristic is null");
         return NULL;
     }
 
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] get value in Characteristic");
+    OIC_LOG(DEBUG, TAG, "get value in Characteristic");
     jmethodID jni_mid_getValue = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic, "getValue",
-            "()[B");
-    if(!jni_mid_getValue)
+                                                     "()[B");
+    if (!jni_mid_getValue)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_mid_getValue is null");
+        OIC_LOG(ERROR, TAG, "jni_mid_getValue is null");
         return NULL;
     }
 
-    jbyteArray jni_obj_data_array =  (*env)->CallObjectMethod(env, characteristic, jni_mid_getValue);
+    jbyteArray jni_obj_data_array = (*env)->CallObjectMethod(env, characteristic,
+                                                             jni_mid_getValue);
     return jni_obj_data_array;
 }
 
-
-void CANativeCreateUUIDList()
+CAResult_t CALEClientCreateUUIDList()
 {
-    jboolean isAttached = FALSE;
+    if (!g_jvm)
+    {
+        OIC_LOG(ERROR, TAG, "g_jvm is null");
+        return CA_STATUS_FAILED;
+    }
+
+    bool isAttached = false;
     JNIEnv* env;
-    jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6);
-    if(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, "Could not get JNIEnv pointer");
+        OIC_LOG(INFO, 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 has failed");
+            return CA_STATUS_FAILED;
         }
-        isAttached = TRUE;
+        isAttached = true;
     }
 
     // create new object array
     jclass jni_cid_uuid_list = (*env)->FindClass(env, CLASSPATH_BT_UUID);
-    if(!jni_cid_uuid_list)
+    if (!jni_cid_uuid_list)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_cid_uuid_list is null");
-        return;
+        OIC_LOG(ERROR, TAG, "jni_cid_uuid_list is null");
+        goto error_exit;
     }
 
-    jobjectArray jni_obj_uuid_list = (jobjectArray)(*env)->NewObjectArray(env, 1, jni_cid_uuid_list, NULL);
-    if(!jni_obj_uuid_list)
+    jobjectArray jni_obj_uuid_list = (jobjectArray)(*env)->NewObjectArray(env, 1,
+                                                                          jni_cid_uuid_list, NULL);
+    if (!jni_obj_uuid_list)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_obj_uuid_list is null");
-        return;
+        OIC_LOG(ERROR, TAG, "jni_obj_uuid_list is null");
+        goto error_exit;
     }
 
-    // remove previous list and create list again
-    CANativeRemoveAllDevices(env);
-    CANativeCreateScanDeviceList(env);
-
     // make uuid list
-    jobject jni_obj_uuid = CANativeGetUUIDObject(env, IOTIVITY_GATT_SERVIE_UUID);
+    jobject jni_obj_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
+    if (!jni_obj_uuid)
+    {
+        OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
+        goto error_exit;
+    }
     (*env)->SetObjectArrayElement(env, jni_obj_uuid_list, 0, jni_obj_uuid);
 
-    gUUIDList = (jobjectArray)(*env)->NewGlobalRef(env, jni_obj_uuid_list);
+    g_uuidList = (jobjectArray)(*env)->NewGlobalRef(env, jni_obj_uuid_list);
 
-    if(isAttached)
+    if (isAttached)
+    {
         (*g_jvm)->DetachCurrentThread(g_jvm);
-}
+    }
 
-void CANativeCreateScanDeviceList(JNIEnv *env)
-{
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeCreateScanDeviceList");
+    return CA_STATUS_OK;
 
-    // create new object array
-    if (gdeviceList == NULL)
-    {
-        OIC_LOG_V(DEBUG, TAG, "Create device list");
+    // error label.
+error_exit:
 
-        gdeviceList = u_arraylist_create();
+    if (isAttached)
+    {
+        (*g_jvm)->DetachCurrentThread(g_jvm);
     }
+    return CA_STATUS_FAILED;
 }
 
-void CANativeAddScanDeviceToList(JNIEnv *env, jobject device)
+CAResult_t CALEClientSetUUIDToDescriptor(JNIEnv *env, jobject bluetoothGatt,
+                                         jobject characteristic)
 {
-    if(!device)
+    VERIFY_NON_NULL(env, TAG, "env is null");
+    VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
+    VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
+
+    if (!CALEIsEnableBTAdapter(env))
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] device is null");
-        return;
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return CA_ADAPTER_NOT_ENABLED;
     }
 
-    if(!gdeviceList)
+    OIC_LOG(DEBUG, TAG, "CALEClientSetUUIDToDescriptor");
+    jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(env, "android/bluetooth/"
+                                                            "BluetoothGattCharacteristic");
+    if (!jni_cid_BTGattCharacteristic)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] gdevice_list is null");
-        return;
+        OIC_LOG(ERROR, TAG, "jni_cid_BTGattCharacteristic is null");
+        return CA_STATUS_FAILED;
     }
 
-    jstring jni_remoteAddress = CANativeGetAddressFromBTDevice(env, device);
-    if(!jni_remoteAddress)
+    OIC_LOG(DEBUG, TAG, "set value in Characteristic");
+    jmethodID jni_mid_getDescriptor = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic,
+                                                          "getDescriptor",
+                                                          "(Ljava/util/UUID;)Landroid/bluetooth/"
+                                                          "BluetoothGattDescriptor;");
+    if (!jni_mid_getDescriptor)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_remoteAddress is null");
-        return;
+        OIC_LOG(ERROR, TAG, "jni_mid_getDescriptor is null");
+        return CA_STATUS_FAILED;
     }
 
-    const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
+    jobject jni_obj_cc_uuid = CALEClientGetUUIDObject(env, OIC_GATT_CHARACTERISTIC_CONFIG_UUID);
+    if (!jni_obj_cc_uuid)
+    {
+        OIC_LOG(ERROR, TAG, "jni_obj_cc_uuid is null");
+        return CA_STATUS_FAILED;
+    }
 
-    if(!CANativeIsDeviceInList(env, remoteAddress)) {
-        jobject gdevice = (*env)->NewGlobalRef(env, device);
-        u_arraylist_add(gdeviceList, gdevice);
-        OIC_LOG_V(DEBUG, TAG, "Set Object to Array as Element");
+    OIC_LOG(DEBUG, TAG, "request to get descriptor");
+    jobject jni_obj_descriptor = (*env)->CallObjectMethod(env, characteristic,
+                                                          jni_mid_getDescriptor, jni_obj_cc_uuid);
+    if (!jni_obj_descriptor)
+    {
+        OIC_LOG(INFO, TAG, "jni_obj_descriptor is null");
+        return CA_NOT_SUPPORTED;
     }
-}
 
-jboolean CANativeIsDeviceInList(JNIEnv *env, const char* remoteAddress){
-    // get address value from device list
+    OIC_LOG(DEBUG, TAG, "set value in descriptor");
+    jclass jni_cid_descriptor = (*env)->FindClass(env,
+                                                  "android/bluetooth/BluetoothGattDescriptor");
+    if (!jni_cid_descriptor)
+    {
+        OIC_LOG(ERROR, TAG, "jni_cid_descriptor is null");
+        return CA_STATUS_FAILED;
+    }
 
-    jint index;
-    for (index = 0; index < u_arraylist_length(gdeviceList); index++)
+    jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_descriptor, "setValue", "([B)Z");
+    if (!jni_mid_setValue)
     {
-        jobject jarrayObj = (jobject) u_arraylist_get(gdeviceList, index);
-        if(!jarrayObj)
-        {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] jarrayObj is null");
-            return TRUE;
-        }
+        OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
+        return CA_STATUS_FAILED;
+    }
 
-        jstring jni_setAddress = CANativeGetAddressFromBTDevice(env, jarrayObj);
-        if(!jni_setAddress)
-        {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_setAddress is null");
-            return TRUE;
-        }
+    jfieldID jni_fid_NotiValue = (*env)->GetStaticFieldID(env, jni_cid_descriptor,
+                                                          "ENABLE_NOTIFICATION_VALUE", "[B");
+    if (!jni_fid_NotiValue)
+    {
+        OIC_LOG(ERROR, TAG, "jni_fid_NotiValue is null");
+        return CA_STATUS_FAILED;
+    }
 
-        const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
+    OIC_LOG(DEBUG, TAG, "get ENABLE_NOTIFICATION_VALUE");
 
-        if(!strcmp(remoteAddress, setAddress))
-        {
-            OIC_LOG_V(DEBUG, TAG, "the device is already set");
-            return TRUE;
-        }
-        else
-        {
-            continue;
-        }
+    jboolean jni_setvalue = (*env)->CallBooleanMethod(
+            env, jni_obj_descriptor, jni_mid_setValue,
+            (jbyteArray)(*env)->GetStaticObjectField(env, jni_cid_descriptor, jni_fid_NotiValue));
+    if (jni_setvalue)
+    {
+        OIC_LOG(DEBUG, TAG, "setValue success");
+    }
+    else
+    {
+        OIC_LOG(ERROR, TAG, "setValue has failed");
+        return CA_STATUS_FAILED;
+    }
+
+    jclass jni_cid_gatt = (*env)->FindClass(env, "android/bluetooth/BluetoothGatt");
+    if (!jni_cid_gatt)
+    {
+        OIC_LOG(ERROR, TAG, "jni_cid_gatt is null");
+        return CA_STATUS_FAILED;
+    }
+
+    OIC_LOG(DEBUG, TAG, "write Descriptor in gatt object");
+    jmethodID jni_mid_writeDescriptor = (*env)->GetMethodID(env, jni_cid_gatt, "writeDescriptor",
+                                                            "(Landroid/bluetooth/"
+                                                            "BluetoothGattDescriptor;)Z");
+    if (!jni_mid_writeDescriptor)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_writeDescriptor is null");
+        return CA_STATUS_FAILED;
+    }
+
+    OIC_LOG(DEBUG, TAG, "request to write descriptor");
+    jboolean jni_ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_writeDescriptor,
+                                                 jni_obj_descriptor);
+    if (jni_ret)
+    {
+        OIC_LOG(DEBUG, TAG, "writeDescriptor success");
+    }
+    else
+    {
+        OIC_LOG(ERROR, TAG, "writeDescriptor has failed");
+        return CA_STATUS_FAILED;
     }
 
-    OIC_LOG_V(DEBUG, TAG, "there are no the device in list. we can add");
-    return FALSE;
+    return CA_STATUS_OK;
 }
 
-void CANativeRemoveAllDevices(JNIEnv *env)
+void CALEClientCreateScanDeviceList(JNIEnv *env)
 {
-    OIC_LOG_V(DEBUG, TAG, "CANativeRemoveAllDevices");
+    OIC_LOG(DEBUG, TAG, "CALEClientCreateScanDeviceList");
+    VERIFY_NON_NULL_VOID(env, TAG, "env is null");
 
-    if(!gdeviceList)
+    ca_mutex_lock(g_deviceListMutex);
+    // create new object array
+    if (g_deviceList == NULL)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] gdeviceList is null");
-        return;
+        OIC_LOG(DEBUG, TAG, "Create device list");
+
+        g_deviceList = u_arraylist_create();
     }
+    ca_mutex_unlock(g_deviceListMutex);
+}
+
+CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device)
+{
+    VERIFY_NON_NULL(device, TAG, "device is null");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+
+    ca_mutex_lock(g_deviceListMutex);
 
-    jint index;
-    for (index = 0; index < u_arraylist_length(gdeviceList); index++)
+    if (!g_deviceList)
     {
-        jobject jarrayObj = (jobject) u_arraylist_get(gdeviceList, index);
-        if(!jarrayObj)
-        {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] jarrayObj is null");
-            return;
-        }
-        (*env)->DeleteGlobalRef(env, jarrayObj);
+        OIC_LOG(ERROR, TAG, "gdevice_list is null");
+        ca_mutex_unlock(g_deviceListMutex);
+        return CA_STATUS_FAILED;
     }
 
-    OICFree(gdeviceList);
-    gdeviceList = NULL;
-    return;
+    jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
+    if (!jni_remoteAddress)
+    {
+        OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
+        ca_mutex_unlock(g_deviceListMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
+    if (!remoteAddress)
+    {
+        OIC_LOG(ERROR, TAG, "remoteAddress is null");
+        ca_mutex_unlock(g_deviceListMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    if (!CALEClientIsDeviceInScanDeviceList(env, remoteAddress))
+    {
+        jobject gdevice = (*env)->NewGlobalRef(env, device);
+        u_arraylist_add(g_deviceList, gdevice);
+        ca_cond_signal(g_deviceDescCond);
+        OIC_LOG_V(DEBUG, TAG, "Added this BT Device[%s] in the List", remoteAddress);
+    }
+    (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
+
+    ca_mutex_unlock(g_deviceListMutex);
+
+    return CA_STATUS_OK;
 }
 
-void CANativeRemoveDevice(JNIEnv *env, jstring address)
+bool CALEClientIsDeviceInScanDeviceList(JNIEnv *env, const char* remoteAddress)
 {
-    OIC_LOG_V(DEBUG, TAG, "CANativeRemoveDevice");
+    VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
+    VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
 
-    if(!gdeviceList)
+    if (!g_deviceList)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] gdeviceList is null");
-        return;
+        OIC_LOG(DEBUG, TAG, "g_deviceList is null");
+        return true;
     }
 
-    jint index;
-    for (index = 0; index < u_arraylist_length(gdeviceList); index++)
+    uint32_t length = u_arraylist_length(g_deviceList);
+    for (uint32_t index = 0; index < length; index++)
     {
-        jobject jarrayObj = (jobject) u_arraylist_get(gdeviceList, index);
-        if(!jarrayObj)
+        jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
+        if (!jarrayObj)
         {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] jarrayObj is null");
-            return;
+            OIC_LOG(ERROR, TAG, "jarrayObj is null");
+            return true;
         }
 
-        jstring jni_setAddress = CANativeGetAddressFromBTDevice(env, jarrayObj);
-        if(!jni_setAddress)
+        jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
+        if (!jni_setAddress)
         {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_setAddress is null");
-            return;
+            OIC_LOG(ERROR, TAG, "jni_setAddress is null");
+            return true;
         }
-        const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
-        const char* remoteAddress = (*env)->GetStringUTFChars(env, address, NULL);
 
-        if(!strcmp(setAddress, remoteAddress))
+        const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
+        if (!setAddress)
         {
-            OIC_LOG_V(DEBUG, TAG, "[BLE][Native] remove object : %s", remoteAddress);
-            (*env)->DeleteGlobalRef(env, jarrayObj);
+            OIC_LOG(ERROR, TAG, "setAddress is null");
+            return true;
+        }
 
-            CAReorderingDeviceList(index);
-            return;
+        if (!strcmp(remoteAddress, setAddress))
+        {
+            (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+            return true;
         }
+
+        (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
     }
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] there are no target object");
-    return;
+
+    OIC_LOG(DEBUG, TAG, "there are no the device in list. we can add");
+
+    return false;
 }
 
-void CAReorderingDeviceList(uint32_t index)
+CAResult_t CALEClientRemoveAllScanDevices(JNIEnv *env)
 {
-    if (index >= gdeviceList->length)
+    OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllScanDevices");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+
+    ca_mutex_lock(g_deviceListMutex);
+
+    if (!g_deviceList)
     {
-        return;
+        OIC_LOG(ERROR, TAG, "g_deviceList is null");
+        ca_mutex_unlock(g_deviceListMutex);
+        return CA_STATUS_FAILED;
     }
 
-    if (index < gdeviceList->length - 1)
+    uint32_t length = u_arraylist_length(g_deviceList);
+    for (uint32_t index = 0; index < length; index++)
     {
-        memmove(&gdeviceList->data[index], &gdeviceList->data[index + 1],
-                (gdeviceList->length - index - 1) * sizeof(void *));
+        jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
+        if (!jarrayObj)
+        {
+            OIC_LOG(ERROR, TAG, "jarrayObj is null");
+            continue;
+        }
+        (*env)->DeleteGlobalRef(env, jarrayObj);
     }
 
-    gdeviceList->size--;
-    gdeviceList->length--;
+    OICFree(g_deviceList);
+    g_deviceList = NULL;
+
+    ca_mutex_unlock(g_deviceListMutex);
+    return CA_STATUS_OK;
 }
 
-/**
- * Gatt Object List
- */
-void CANativeCreateGattObjList(JNIEnv *env)
+CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address)
 {
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeCreateGattObjList");
+    OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceInScanDeviceList");
+    VERIFY_NON_NULL(address, TAG, "address is null");
+    VERIFY_NON_NULL(env, TAG, "env is null");
 
-    // create new object array
-    if (gGattObjectList == NULL)
+    ca_mutex_lock(g_deviceListMutex);
+
+    if (!g_deviceList)
     {
-        OIC_LOG_V(DEBUG, TAG, "Create Gatt object list");
+        OIC_LOG(ERROR, TAG, "g_deviceList is null");
+        ca_mutex_unlock(g_deviceListMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    uint32_t length = u_arraylist_length(g_deviceList);
+    for (uint32_t index = 0; index < length; index++)
+    {
+        jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
+        if (!jarrayObj)
+        {
+            OIC_LOG(ERROR, TAG, "jarrayObj is null");
+            ca_mutex_unlock(g_deviceListMutex);
+            return CA_STATUS_FAILED;
+        }
+
+        jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
+        if (!jni_setAddress)
+        {
+            OIC_LOG(ERROR, TAG, "jni_setAddress is null");
+            ca_mutex_unlock(g_deviceListMutex);
+            return CA_STATUS_FAILED;
+        }
 
-        gGattObjectList = u_arraylist_create();
+        const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
+        if (!setAddress)
+        {
+            OIC_LOG(ERROR, TAG, "setAddress is null");
+            ca_mutex_unlock(g_deviceListMutex);
+            return CA_STATUS_FAILED;
+        }
+
+        const char* remoteAddress = (*env)->GetStringUTFChars(env, address, NULL);
+        if (!remoteAddress)
+        {
+            OIC_LOG(ERROR, TAG, "remoteAddress is null");
+            (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+            ca_mutex_unlock(g_deviceListMutex);
+            return CA_STATUS_FAILED;
+        }
+
+        if (!strcmp(setAddress, remoteAddress))
+        {
+            OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
+            (*env)->DeleteGlobalRef(env, jarrayObj);
+            (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+            (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
+
+            if (NULL == u_arraylist_remove(g_deviceList, index))
+            {
+                OIC_LOG(ERROR, TAG, "List removal failed.");
+                ca_mutex_unlock(g_deviceListMutex);
+                return CA_STATUS_FAILED;
+            }
+            ca_mutex_unlock(g_deviceListMutex);
+            return CA_STATUS_OK;
+        }
+        (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+        (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
     }
+
+    ca_mutex_unlock(g_deviceListMutex);
+    OIC_LOG(DEBUG, TAG, "There are no object in the device list");
+
+    return CA_STATUS_OK;
 }
 
-void CANativeAddGattobjToList(JNIEnv *env, jobject gatt)
+/**
+ * Gatt Object List
+ */
+
+CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt)
 {
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeAddGattobjToList");
+    OIC_LOG(INFO, TAG, "CALEClientAddGattobjToList");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+    VERIFY_NON_NULL(gatt, TAG, "gatt is null");
 
-    if(!gatt)
-    {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] gatt is null");
-        return;
-    }
+    ca_mutex_lock(g_gattObjectMutex);
 
-    if(!gGattObjectList)
+    if (!g_gattObjectList)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] gGattObjectList is null");
-        return;
+        OIC_LOG(ERROR, TAG, "g_gattObjectList is not available");
+        ca_mutex_unlock(g_gattObjectMutex);
+        return CA_STATUS_FAILED;
     }
 
-    jstring jni_remoteAddress = CANativeGetAddressFromGattObj(env, gatt);
-    if(!jni_remoteAddress)
+    jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
+    if (!jni_remoteAddress)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_remoteAddress is null");
-        return;
+        OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
+        ca_mutex_unlock(g_gattObjectMutex);
+        return CA_STATUS_FAILED;
     }
 
     const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
+    if (!remoteAddress)
+    {
+        OIC_LOG(ERROR, TAG, "remoteAddress is null");
+        ca_mutex_unlock(g_gattObjectMutex);
+        return CA_STATUS_FAILED;
+    }
 
-    if(!CANativeIsGattObjInList(env, remoteAddress))
+    OIC_LOG_V(INFO, TAG, "remote address : %s", remoteAddress);
+    if (!CALEClientIsGattObjInList(env, remoteAddress))
     {
-        jobject gGatt = (*env)->NewGlobalRef(env, gatt);
-        u_arraylist_add(gGattObjectList, gGatt);
-        OIC_LOG_V(DEBUG, TAG, "Set Object to Array as Element");
+        jobject newGatt = (*env)->NewGlobalRef(env, gatt);
+        u_arraylist_add(g_gattObjectList, newGatt);
+        OIC_LOG(INFO, TAG, "Set GATT Object to Array as Element");
     }
+
+    (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
+    ca_mutex_unlock(g_gattObjectMutex);
+    return CA_STATUS_OK;
 }
 
-jboolean CANativeIsGattObjInList(JNIEnv *env, const char* remoteAddress)
+bool CALEClientIsGattObjInList(JNIEnv *env, const char* remoteAddress)
 {
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeIsGattObjInList");
+    OIC_LOG(DEBUG, TAG, "CALEClientIsGattObjInList");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+    VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
 
-    jint index;
-    for (index = 0; index < u_arraylist_length(gGattObjectList); index++)
+    uint32_t length = u_arraylist_length(g_gattObjectList);
+    for (uint32_t index = 0; index < length; index++)
     {
 
-        jobject jarrayObj = (jobject) u_arraylist_get(gGattObjectList, index);
-        if(!jarrayObj)
+        jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
+        if (!jarrayObj)
         {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] jarrayObj is null");
-            return TRUE;
+            OIC_LOG(ERROR, TAG, "jarrayObj is null");
+            return true;
         }
 
-        jstring jni_setAddress = CANativeGetAddressFromGattObj(env, jarrayObj);
-        if(!jni_setAddress)
+        jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
+        if (!jni_setAddress)
         {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_setAddress is null");
-            return TRUE;
+            OIC_LOG(ERROR, TAG, "jni_setAddress is null");
+            return true;
         }
 
         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
+        if (!setAddress)
+        {
+            OIC_LOG(ERROR, TAG, "setAddress is null");
+            return true;
+        }
 
-        if(!strcmp(remoteAddress, setAddress))
+        if (!strcmp(remoteAddress, setAddress))
         {
-            OIC_LOG_V(DEBUG, TAG, "the device is already set");
-            return TRUE;
+            OIC_LOG(DEBUG, TAG, "the device is already set");
+            (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+            return true;
         }
         else
         {
+            (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
             continue;
         }
     }
 
-    OIC_LOG_V(DEBUG, TAG, "there are no the gatt obejct in list. we can add");
-    return FALSE;
+    OIC_LOG(DEBUG, TAG, "There are no GATT object in list. it can be added");
+    return false;
 }
 
-void CANativeRemoveAllGattObjsList(JNIEnv *env)
+jobject CALEClientGetGattObjInList(JNIEnv *env, const char* remoteAddress)
 {
-    OIC_LOG_V(DEBUG, TAG, "CANativeRemoveAllGattObjsList");
+    OIC_LOG(DEBUG, TAG, "CALEClientGetGattObjInList");
+    VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
+    VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
 
-    if(!gGattObjectList)
+    ca_mutex_lock(g_gattObjectMutex);
+    uint32_t length = u_arraylist_length(g_gattObjectList);
+    for (uint32_t index = 0; index < length; index++)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] gGattObjectList is null");
-        return;
+        jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
+        if (!jarrayObj)
+        {
+            OIC_LOG(ERROR, TAG, "jarrayObj is null");
+            ca_mutex_unlock(g_gattObjectMutex);
+            return NULL;
+        }
+
+        jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
+        if (!jni_setAddress)
+        {
+            OIC_LOG(ERROR, TAG, "jni_setAddress is null");
+            ca_mutex_unlock(g_gattObjectMutex);
+            return NULL;
+        }
+
+        const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
+        if (!setAddress)
+        {
+            OIC_LOG(ERROR, TAG, "setAddress is null");
+            ca_mutex_unlock(g_gattObjectMutex);
+            return NULL;
+        }
+
+        if (!strcmp(remoteAddress, setAddress))
+        {
+            OIC_LOG(DEBUG, TAG, "the device is already set");
+            (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+            ca_mutex_unlock(g_gattObjectMutex);
+            return jarrayObj;
+        }
+        (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+    }
+
+    ca_mutex_unlock(g_gattObjectMutex);
+    OIC_LOG(DEBUG, TAG, "There are no the gatt object in list");
+    return NULL;
+}
+
+CAResult_t CALEClientRemoveAllGattObjs(JNIEnv *env)
+{
+    OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllGattObjs");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+
+    ca_mutex_lock(g_gattObjectMutex);
+    if (!g_gattObjectList)
+    {
+        OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
+        ca_mutex_unlock(g_gattObjectMutex);
+        return CA_STATUS_OK;
     }
 
-    jint index;
-    for (index = 0; index < u_arraylist_length(gGattObjectList); index++)
+    uint32_t length = u_arraylist_length(g_gattObjectList);
+    for (uint32_t index = 0; index < length; index++)
     {
-        jobject jarrayObj = (jobject) u_arraylist_get(gGattObjectList, index);
-        if(!jarrayObj)
+        jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
+        if (!jarrayObj)
         {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] jarrayObj is null");
-            return;
+            OIC_LOG(ERROR, TAG, "jarrayObj is null");
+            continue;
         }
         (*env)->DeleteGlobalRef(env, jarrayObj);
     }
 
-    OICFree(gGattObjectList);
-    gGattObjectList = NULL;
-    return;
+    OICFree(g_gattObjectList);
+    g_gattObjectList = NULL;
+    OIC_LOG(INFO, TAG, "g_gattObjectList is removed");
+    ca_mutex_unlock(g_gattObjectMutex);
+    return CA_STATUS_OK;
 }
 
-void CANativeLEDisconnectAll(JNIEnv *env)
+CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt)
 {
-    OIC_LOG_V(DEBUG, TAG, "CANativeLEDisconnectAll");
+    OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObj");
+    VERIFY_NON_NULL(gatt, TAG, "gatt is null");
+    VERIFY_NON_NULL(env, TAG, "env is null");
 
-    if(!gGattObjectList)
+    ca_mutex_lock(g_gattObjectMutex);
+    if (!g_gattObjectList)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] gGattObjectList is null");
-        return;
+        OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
+        ca_mutex_unlock(g_gattObjectMutex);
+        return CA_STATUS_OK;
     }
 
-    jint index;
-    for (index = 0; index < u_arraylist_length(gGattObjectList); index++)
+    uint32_t length = u_arraylist_length(g_gattObjectList);
+    for (uint32_t index = 0; index < length; index++)
     {
-        jobject jarrayObj = (jobject) u_arraylist_get(gGattObjectList, index);
-        if(!jarrayObj)
+        jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
+        if (!jarrayObj)
         {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] jarrayObj is null");
-            return;
+            OIC_LOG(ERROR, TAG, "jarrayObj is null");
+            ca_mutex_unlock(g_gattObjectMutex);
+            return CA_STATUS_FAILED;
+        }
+
+        jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
+        if (!jni_setAddress)
+        {
+            OIC_LOG(ERROR, TAG, "jni_setAddress is null");
+            ca_mutex_unlock(g_gattObjectMutex);
+            return CA_STATUS_FAILED;
+        }
+
+        const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
+        if (!setAddress)
+        {
+            OIC_LOG(ERROR, TAG, "setAddress is null");
+            ca_mutex_unlock(g_gattObjectMutex);
+            return CA_STATUS_FAILED;
+        }
+
+        jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
+        if (!jni_remoteAddress)
+        {
+            OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
+            (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+            ca_mutex_unlock(g_gattObjectMutex);
+            return CA_STATUS_FAILED;
+        }
+
+        const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
+        if (!remoteAddress)
+        {
+            OIC_LOG(ERROR, TAG, "remoteAddress is null");
+            (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+            ca_mutex_unlock(g_gattObjectMutex);
+            return CA_STATUS_FAILED;
         }
-        CANativeLEDisconnect(env, jarrayObj);
+
+        if (!strcmp(setAddress, remoteAddress))
+        {
+            OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
+            (*env)->DeleteGlobalRef(env, jarrayObj);
+            (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+            (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
+
+            if (NULL == u_arraylist_remove(g_gattObjectList, index))
+            {
+                OIC_LOG(ERROR, TAG, "List removal failed.");
+                ca_mutex_unlock(g_gattObjectMutex);
+                return CA_STATUS_FAILED;
+            }
+            ca_mutex_unlock(g_gattObjectMutex);
+            return CA_STATUS_OK;
+        }
+        (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+        (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
     }
 
-    OICFree(gGattObjectList);
-    gGattObjectList = NULL;
-    return;
+    ca_mutex_unlock(g_gattObjectMutex);
+    OIC_LOG(DEBUG, TAG, "there are no target object");
+    return CA_STATUS_OK;
 }
 
-void CANativeRemoveGattObj(JNIEnv *env, jobject gatt)
+CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr)
 {
-    OIC_LOG_V(DEBUG, TAG, "CANativeRemoveGattObj");
+    OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObjForAddr");
+    VERIFY_NON_NULL(addr, TAG, "addr is null");
+    VERIFY_NON_NULL(env, TAG, "env is null");
 
-    if(!gGattObjectList)
+    ca_mutex_lock(g_gattObjectMutex);
+    if (!g_gattObjectList)
     {
-        OIC_LOG(DEBUG, TAG, "[BLE][Native] gGattObjectList is null");
-        return;
+        OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
+        ca_mutex_unlock(g_gattObjectMutex);
+        return CA_STATUS_OK;
     }
 
-    jint index;
-    for (index = 0; index < u_arraylist_length(gGattObjectList); index++)
+    uint32_t length = u_arraylist_length(g_gattObjectList);
+    for (uint32_t index = 0; index < length; index++)
     {
-        jobject jarrayObj = (jobject) u_arraylist_get(gGattObjectList, index);
-        if(!jarrayObj)
+        jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
+        if (!jarrayObj)
         {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] jarrayObj is null");
-            return;
+            OIC_LOG(ERROR, TAG, "jarrayObj is null");
+            ca_mutex_unlock(g_gattObjectMutex);
+            return CA_STATUS_FAILED;
         }
 
-        jstring jni_setAddress = CANativeGetAddressFromGattObj(env, jarrayObj);
-        if(!jni_setAddress)
+        jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
+        if (!jni_setAddress)
         {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_setAddress is null");
-            return;
+            OIC_LOG(ERROR, TAG, "jni_setAddress is null");
+            ca_mutex_unlock(g_gattObjectMutex);
+            return CA_STATUS_FAILED;
         }
+
         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
+        if (!setAddress)
+        {
+            OIC_LOG(ERROR, TAG, "setAddress is null");
+            ca_mutex_unlock(g_gattObjectMutex);
+            return CA_STATUS_FAILED;
+        }
 
-        jstring jni_remoteAddress = CANativeGetAddressFromGattObj(env, gatt);
-        if(!jni_remoteAddress)
+        const char* remoteAddress = (*env)->GetStringUTFChars(env, addr, NULL);
+        if (!remoteAddress)
         {
-            OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_remoteAddress is null");
-            return;
+            OIC_LOG(ERROR, TAG, "remoteAddress is null");
+            (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+            ca_mutex_unlock(g_gattObjectMutex);
+            return CA_STATUS_FAILED;
         }
-        const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
 
-        if(!strcmp(setAddress, remoteAddress))
+        if (!strcmp(setAddress, remoteAddress))
         {
-            OIC_LOG_V(DEBUG, TAG, "[BLE][Native] remove object : %s", remoteAddress);
+            OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
             (*env)->DeleteGlobalRef(env, jarrayObj);
 
-            CAReorderingGattList(index);
-            return;
+            (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+            (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
+            if (NULL == u_arraylist_remove(g_gattObjectList, index))
+            {
+                OIC_LOG(ERROR, TAG, "List removal failed.");
+                ca_mutex_unlock(g_gattObjectMutex);
+                return CA_STATUS_FAILED;
+            }
+            ca_mutex_unlock(g_gattObjectMutex);
+            return CA_STATUS_OK;
         }
+        (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+        (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
     }
-    OIC_LOG(DEBUG, TAG, "[BLE][Native] there are no target object");
-    return;
+
+    ca_mutex_unlock(g_gattObjectMutex);
+    OIC_LOG(DEBUG, TAG, "there are no target object");
+    return CA_STATUS_FAILED;
 }
 
-void CAReorderingGattList(uint32_t index)
+jstring CALEClientGetLEAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice)
 {
-    if (index >= gGattObjectList->length)
+    OIC_LOG(DEBUG, TAG, "IN - CALEClientGetLEAddressFromBTDevice");
+
+    VERIFY_NON_NULL_RET(env, TAG, "env", NULL);
+    VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice", NULL);
+
+    // get Bluetooth Address
+    jstring jni_btTargetAddress = CALEGetAddressFromBTDevice(env, bluetoothDevice);
+    if (!jni_btTargetAddress)
     {
-        return;
+        OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
+        return NULL;
+    }
+
+    const char* targetAddress = (*env)->GetStringUTFChars(env, jni_btTargetAddress, NULL);
+    if (!targetAddress)
+    {
+        OIC_LOG(ERROR, TAG, "targetAddress is not available");
+        return NULL;
+    }
+
+    // get method ID of getDevice()
+    jclass jni_cid_gattdevice_list = (*env)->FindClass(env, CLASSPATH_BT_GATT);
+    if (!jni_cid_gattdevice_list)
+    {
+        OIC_LOG(ERROR, TAG, "jni_cid_gattdevice_list is null");
+        (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
+        return NULL;
+    }
+
+    jmethodID jni_mid_getDevice = (*env)->GetMethodID(env, jni_cid_gattdevice_list, "getDevice",
+                                                      METHODID_BT_DEVICE);
+    if (!jni_mid_getDevice)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
+        (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
+        return NULL;
     }
 
-    if (index < gGattObjectList->length - 1)
+    size_t length = u_arraylist_length(g_gattObjectList);
+    for (size_t index = 0; index < length; index++)
     {
-        memmove(&gGattObjectList->data[index], &gGattObjectList->data[index + 1],
-                (gGattObjectList->length - index - 1) * sizeof(void *));
+        jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
+        if (!jarrayObj)
+        {
+            OIC_LOG(ERROR, TAG, "jarrayObj is null");
+            (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
+            return NULL;
+        }
+
+        OIC_LOG(DEBUG, TAG, "CALL API - bluetoothGatt.getDevice()");
+        jobject jni_obj_device = (*env)->CallObjectMethod(env, jarrayObj, jni_mid_getDevice);
+        if (!jni_obj_device)
+        {
+            OIC_LOG(ERROR, TAG, "jni_obj_device is null");
+            (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
+            return NULL;
+        }
+
+        jstring jni_btAddress = CALEGetAddressFromBTDevice(env, jni_obj_device);
+        if (!jni_btAddress)
+        {
+            OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
+            (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
+            return NULL;
+        }
+
+        const char* btAddress = (*env)->GetStringUTFChars(env, jni_btAddress, NULL);
+        if (!btAddress)
+        {
+            OIC_LOG(ERROR, TAG, "btAddress is not available");
+            (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
+            return NULL;
+        }
+
+        OIC_LOG_V(DEBUG, TAG, "targetAddress : %s", targetAddress);
+        OIC_LOG_V(DEBUG, TAG, "btAddress : %s", btAddress);
+        if (!strcmp(targetAddress, btAddress))
+        {
+            OIC_LOG(DEBUG, TAG, "Found Gatt object from BT device");
+
+            // get LE address
+            jstring jni_LEAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
+            if (!jni_LEAddress)
+            {
+                OIC_LOG(ERROR, TAG, "jni_LEAddress is null");
+            }
+            (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
+            (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
+            (*env)->DeleteLocalRef(env, jni_btAddress);
+            (*env)->DeleteLocalRef(env, jni_obj_device);
+            return jni_LEAddress;
+        }
+        (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
+        (*env)->DeleteLocalRef(env, jni_btAddress);
+        (*env)->DeleteLocalRef(env, jni_obj_device);
     }
 
-    gGattObjectList->size--;
-    gGattObjectList->length--;
+    OIC_LOG(DEBUG, TAG, "OUT - CALEClientGetLEAddressFromBTDevice");
+    return NULL;
 }
 
-void CANativeupdateSendCnt(JNIEnv *env)
+/**
+ * BT State List
+ */
+
+CAResult_t CALEClientUpdateDeviceState(const char* address, uint32_t connectedState,
+                                       uint16_t notificationState, uint16_t sendState)
 {
-    // mutex lock
-    u_mutex_lock(gThreadMutex);
+    VERIFY_NON_NULL(address, TAG, "address is null");
+
+    CALEState_t *newstate = (CALEState_t*) OICMalloc(sizeof(CALEState_t));
+    if (!newstate)
+    {
+        OIC_LOG(ERROR, TAG, "out of memory");
+        return CA_MEMORY_ALLOC_FAILED;
+    }
+
+    if (strlen(address) > CA_MACADDR_SIZE)
+    {
+        OIC_LOG(ERROR, TAG, "address is not proper");
+        OICFree(newstate);
+        return CA_STATUS_FAILED;
+    }
+
+    OICStrcpy(newstate->address, sizeof(newstate->address), address);
+    newstate->connectedState = connectedState;
+    newstate->notificationState = notificationState;
+    newstate->sendState = sendState;
+    return CALEClientAddDeviceStateToList(newstate);
+}
+
+CAResult_t CALEClientAddDeviceStateToList(CALEState_t* state)
+{
+    VERIFY_NON_NULL(state, TAG, "state is null");
+
+    ca_mutex_lock(g_deviceStateListMutex);
 
-    gCurrentSentCnt++;
+    if (!g_deviceStateList)
+    {
+        OIC_LOG(ERROR, TAG, "gdevice_list is null");
+        ca_mutex_unlock(g_deviceStateListMutex);
+        return CA_STATUS_FAILED;
+    }
 
-    if(gTargetCnt <= gCurrentSentCnt)
+    if (CALEClientIsDeviceInList(state->address))
     {
-        gTargetCnt = 0;
-        gCurrentSentCnt = 0;
+        CALEState_t* curState = CALEClientGetStateInfo(state->address);
+        if(!curState)
+        {
+            OIC_LOG(ERROR, TAG, "curState is null");
+            ca_mutex_unlock(g_deviceStateListMutex);
+            return CA_STATUS_FAILED;
+        }
 
-        if(gSendBuffer)
+        if (STATE_CHARACTER_NO_CHANGE == state->notificationState)
         {
-            (*env)->DeleteGlobalRef(env, gSendBuffer);
-            gSendBuffer = NULL;
+            state->notificationState = curState->notificationState;
+        }
+
+        // delete previous state for update new state
+        CAResult_t res = CALEClientRemoveDeviceState(state->address);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "CALEClientRemoveDeviceState has failed");
+            ca_mutex_unlock(g_deviceStateListMutex);
+            return res;
         }
-        // notity the thread
-        u_cond_signal(gThreadCond);
-        gIsFinishSendData = TRUE;
-        OIC_LOG(DEBUG, TAG, "set signal for send data");
     }
-    // mutex unlock
-    u_mutex_unlock(gThreadMutex);
+    u_arraylist_add(g_deviceStateList, state); // update new state
+    OIC_LOG_V(INFO, TAG, "Set State Info to List : %d, %d, %s",
+              state->connectedState, state->notificationState, state->address);
+
+    ca_mutex_unlock(g_deviceStateListMutex);
+    return CA_STATUS_OK;
+}
+
+bool CALEClientIsDeviceInList(const char* remoteAddress)
+{
+    VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
+
+    if (!g_deviceStateList)
+    {
+        OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
+        return false;
+    }
+
+    uint32_t length = u_arraylist_length(g_deviceStateList);
+    for (uint32_t index = 0; index < length; index++)
+    {
+        CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
+        if (!state)
+        {
+            OIC_LOG(ERROR, TAG, "CALEState_t object is null");
+            return false;
+        }
+
+        if (!strcmp(remoteAddress, state->address))
+        {
+            OIC_LOG(DEBUG, TAG, "the device is already set");
+            return true;
+        }
+        else
+        {
+            continue;
+        }
+    }
+
+    OIC_LOG(DEBUG, TAG, "there are no the device in list.");
+    return false;
+}
+
+CAResult_t CALEClientRemoveAllDeviceState()
+{
+    OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllDeviceState");
+
+    ca_mutex_lock(g_deviceStateListMutex);
+    if (!g_deviceStateList)
+    {
+        OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
+        ca_mutex_unlock(g_deviceStateListMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    uint32_t length = u_arraylist_length(g_deviceStateList);
+    for (uint32_t index = 0; index < length; index++)
+    {
+        CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
+        if (!state)
+        {
+            OIC_LOG(ERROR, TAG, "jarrayObj is null");
+            continue;
+        }
+        OICFree(state);
+    }
+
+    OICFree(g_deviceStateList);
+    g_deviceStateList = NULL;
+    ca_mutex_unlock(g_deviceStateListMutex);
+
+    return CA_STATUS_OK;
+}
+
+CAResult_t CALEClientRemoveDeviceState(const char* remoteAddress)
+{
+    OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceState");
+    VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
+
+    if (!g_deviceStateList)
+    {
+        OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
+        return CA_STATUS_FAILED;
+    }
+
+    uint32_t length = u_arraylist_length(g_deviceStateList);
+    for (uint32_t index = 0; index < length; index++)
+    {
+        CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
+        if (!state)
+        {
+            OIC_LOG(ERROR, TAG, "CALEState_t object is null");
+            continue;
+        }
+
+        if (!strcmp(state->address, remoteAddress))
+        {
+            OIC_LOG_V(DEBUG, TAG, "remove state : %s", state->address);
+
+            CALEState_t* targetState  = (CALEState_t*)u_arraylist_remove(g_deviceStateList,
+                                                                         index);
+            if (NULL == targetState)
+            {
+                OIC_LOG(ERROR, TAG, "List removal failed.");
+                return CA_STATUS_FAILED;
+            }
+
+            OICFree(targetState);
+            return CA_STATUS_OK;
+        }
+    }
+
+    return CA_STATUS_OK;
+}
+
+CALEState_t* CALEClientGetStateInfo(const char* remoteAddress)
+{
+    OIC_LOG(DEBUG, TAG, "CALEClientGetStateInfo");
+    VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
+
+    if (!g_deviceStateList)
+    {
+        OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
+        return NULL;
+    }
+
+    uint32_t length = u_arraylist_length(g_deviceStateList);
+    OIC_LOG_V(DEBUG, TAG, "CALEClientGetStateInfo : %d", length);
+
+    for (uint32_t index = 0; index < length; index++)
+    {
+        CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
+        if (!state)
+        {
+            OIC_LOG(ERROR, TAG, "CALEState_t object is null");
+            continue;
+        }
+
+        OIC_LOG_V(DEBUG, TAG, "target address : %s", remoteAddress);
+        OIC_LOG_V(DEBUG, TAG, "state address : %s", state->address);
+
+        if (!strcmp(state->address, remoteAddress))
+        {
+            OIC_LOG_V(DEBUG, TAG, "get state : %s", remoteAddress);
+            return state;
+        }
+    }
+    return NULL;
+}
+
+bool CALEClientIsConnectedDevice(const char* remoteAddress)
+{
+    OIC_LOG(DEBUG, TAG, "CALEClientIsConnectedDevice");
+    VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
+
+    ca_mutex_lock(g_deviceStateListMutex);
+    if (!g_deviceStateList)
+    {
+        OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
+        ca_mutex_unlock(g_deviceStateListMutex);
+        return false;
+    }
+
+    uint32_t length = u_arraylist_length(g_deviceStateList);
+    for (uint32_t index = 0; index < length; index++)
+    {
+        CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
+        if (!state)
+        {
+            OIC_LOG(ERROR, TAG, "CALEState_t object is null");
+            continue;
+        }
+
+        if (!strcmp(state->address, remoteAddress))
+        {
+            OIC_LOG(DEBUG, TAG, "check whether it is connected or not");
+
+            if (STATE_CONNECTED == state->connectedState)
+            {
+                ca_mutex_unlock(g_deviceStateListMutex);
+                return true;
+            }
+            else
+            {
+                ca_mutex_unlock(g_deviceStateListMutex);
+                return false;
+            }
+        }
+    }
+    ca_mutex_unlock(g_deviceStateListMutex);
+    return false;
+}
+
+bool CALEClientIsSetCharacteristic(const char* remoteAddress)
+{
+    OIC_LOG(DEBUG, TAG, "CALEClientIsSetCharacteristic");
+    VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
+
+    ca_mutex_lock(g_deviceStateListMutex);
+    if (!g_deviceStateList)
+    {
+        OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
+        ca_mutex_unlock(g_deviceStateListMutex);
+        return false;
+    }
+
+    uint32_t length = u_arraylist_length(g_deviceStateList);
+    for (uint32_t index = 0; index < length; index++)
+    {
+        CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
+        if (!state)
+        {
+            OIC_LOG(ERROR, TAG, "CALEState_t object is null");
+            continue;
+        }
+
+        if (!strcmp(state->address, remoteAddress))
+        {
+            OIC_LOG_V(DEBUG, TAG, "check whether it was set or not:%d", state->notificationState);
+
+            if (STATE_CHARACTER_SET == state->notificationState)
+            {
+                ca_mutex_unlock(g_deviceStateListMutex);
+                return true;
+            }
+            else
+            {
+                ca_mutex_unlock(g_deviceStateListMutex);
+                return false;
+            }
+        }
+    }
+
+    ca_mutex_unlock(g_deviceStateListMutex);
+    return false;
+}
+
+void CALEClientCreateDeviceList()
+{
+    OIC_LOG(DEBUG, TAG, "CALEClientCreateDeviceList");
+
+    // create new object array
+    if (!g_gattObjectList)
+    {
+        OIC_LOG(DEBUG, TAG, "Create g_gattObjectList");
+
+        g_gattObjectList = u_arraylist_create();
+    }
+
+    if (!g_deviceStateList)
+    {
+        OIC_LOG(DEBUG, TAG, "Create g_deviceStateList");
+
+        g_deviceStateList = u_arraylist_create();
+    }
+
+    if (!g_deviceList)
+    {
+        OIC_LOG(DEBUG, TAG, "Create g_deviceList");
+
+        g_deviceList = u_arraylist_create();
+    }
+}
+
+/**
+ * Check Sent Count for remove g_sendBuffer
+ */
+void CALEClientUpdateSendCnt(JNIEnv *env)
+{
+    OIC_LOG(DEBUG, TAG, "CALEClientUpdateSendCnt");
+
+    VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+    // mutex lock
+    ca_mutex_lock(g_threadMutex);
+
+    g_currentSentCnt++;
+
+    if (g_targetCnt <= g_currentSentCnt)
+    {
+        g_targetCnt = 0;
+        g_currentSentCnt = 0;
+
+        if (g_sendBuffer)
+        {
+            (*env)->DeleteGlobalRef(env, g_sendBuffer);
+            g_sendBuffer = NULL;
+        }
+        // notity the thread
+        ca_cond_signal(g_threadCond);
+
+        CALEClientSetSendFinishFlag(true);
+        OIC_LOG(DEBUG, TAG, "set signal for send data");
+    }
+    // mutex unlock
+    ca_mutex_unlock(g_threadMutex);
+}
+
+CAResult_t CALEClientInitGattMutexVaraibles()
+{
+    if (NULL == g_bleReqRespClientCbMutex)
+    {
+        g_bleReqRespClientCbMutex = ca_mutex_new();
+        if (NULL == g_bleReqRespClientCbMutex)
+        {
+            OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+            return CA_STATUS_FAILED;
+        }
+    }
+
+    if (NULL == g_bleServerBDAddressMutex)
+    {
+        g_bleServerBDAddressMutex = ca_mutex_new();
+        if (NULL == g_bleServerBDAddressMutex)
+        {
+            OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+            return CA_STATUS_FAILED;
+        }
+    }
+
+    if (NULL == g_threadMutex)
+    {
+        g_threadMutex = ca_mutex_new();
+        if (NULL == g_threadMutex)
+        {
+            OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+            return CA_STATUS_FAILED;
+        }
+    }
+
+    if (NULL == g_threadSendMutex)
+    {
+        g_threadSendMutex = ca_mutex_new();
+        if (NULL == g_threadSendMutex)
+        {
+            OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+            return CA_STATUS_FAILED;
+        }
+    }
+
+    if (NULL == g_deviceListMutex)
+    {
+        g_deviceListMutex = ca_mutex_new();
+        if (NULL == g_deviceListMutex)
+        {
+            OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+            return CA_STATUS_FAILED;
+        }
+    }
+
+    if (NULL == g_gattObjectMutex)
+    {
+        g_gattObjectMutex = ca_mutex_new();
+        if (NULL == g_gattObjectMutex)
+        {
+            OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+            return CA_STATUS_FAILED;
+        }
+    }
+
+    if (NULL == g_deviceStateListMutex)
+    {
+        g_deviceStateListMutex = ca_mutex_new();
+        if (NULL == g_deviceStateListMutex)
+        {
+            OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+            return CA_STATUS_FAILED;
+        }
+    }
+
+    if (NULL == g_SendFinishMutex)
+    {
+        g_SendFinishMutex = ca_mutex_new();
+        if (NULL == g_SendFinishMutex)
+        {
+            OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+            return CA_STATUS_FAILED;
+        }
+    }
+
+    if (NULL == g_scanMutex)
+    {
+        g_scanMutex = ca_mutex_new();
+        if (NULL == g_scanMutex)
+        {
+            OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+            return CA_STATUS_FAILED;
+        }
+    }
+
+    if (NULL == g_threadWriteCharacteristicMutex)
+    {
+        g_threadWriteCharacteristicMutex = ca_mutex_new();
+        if (NULL == g_threadWriteCharacteristicMutex)
+        {
+            OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+            return CA_STATUS_FAILED;
+        }
+    }
+
+    return CA_STATUS_OK;
+}
+
+void CALEClientTerminateGattMutexVariables()
+{
+    ca_mutex_free(g_bleReqRespClientCbMutex);
+    g_bleReqRespClientCbMutex = NULL;
+
+    ca_mutex_free(g_bleServerBDAddressMutex);
+    g_bleServerBDAddressMutex = NULL;
+
+    ca_mutex_free(g_threadMutex);
+    g_threadMutex = NULL;
+
+    ca_mutex_free(g_threadSendMutex);
+    g_threadSendMutex = NULL;
+
+    ca_mutex_free(g_deviceListMutex);
+    g_deviceListMutex = NULL;
+
+    ca_mutex_free(g_SendFinishMutex);
+    g_SendFinishMutex = NULL;
+
+    ca_mutex_free(g_scanMutex);
+    g_scanMutex = NULL;
+
+    ca_mutex_free(g_threadWriteCharacteristicMutex);
+    g_threadWriteCharacteristicMutex = NULL;
+}
+
+void CALEClientSetSendFinishFlag(bool flag)
+{
+    OIC_LOG_V(DEBUG, TAG, "g_isFinishedSendData is %d", flag);
+
+    ca_mutex_lock(g_SendFinishMutex);
+    g_isFinishedSendData = flag;
+    ca_mutex_unlock(g_SendFinishMutex);
+}
+
+/**
+ * adapter common
+ */
+
+CAResult_t CAStartLEGattClient()
+{
+    CAResult_t res = CALEClientStartMulticastServer();
+    if (CA_STATUS_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "CALEClientStartMulticastServer has failed");
+    }
+    else
+    {
+        g_isStartedLEClient = true;
+    }
+
+    return res;
+}
+
+void CAStopLEGattClient()
+{
+    OIC_LOG(DEBUG, TAG, "CAStopBLEGattClient");
+
+    if (!g_jvm)
+    {
+        OIC_LOG(ERROR, TAG, "g_jvm is null");
+        return;
+    }
+
+    bool isAttached = false;
+    JNIEnv* env;
+    jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
+    if (JNI_OK != res)
+    {
+        OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
+        res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
+
+        if (JNI_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
+            return;
+        }
+        isAttached = true;
+    }
+
+    CAResult_t ret = CALEClientDisconnectAll(env);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
+    }
+
+    ret = CALEClientStopScan();
+    if(CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
+    }
+
+    ca_mutex_lock(g_threadMutex);
+    ca_cond_signal(g_threadCond);
+    ca_mutex_unlock(g_threadMutex);
+
+    ca_mutex_lock(g_threadWriteCharacteristicMutex);
+    ca_cond_signal(g_threadWriteCharacteristicCond);
+    ca_mutex_unlock(g_threadWriteCharacteristicMutex);
+
+    if (isAttached)
+    {
+        (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
+
+}
+
+CAResult_t CAInitializeLEGattClient()
+{
+    OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
+    CALEClientInitialize();
+    return CA_STATUS_OK;
+}
+
+void CATerminateLEGattClient()
+{
+    OIC_LOG(DEBUG, TAG, "Terminate GATT Client");
+    CAStopLEGattClient();
+    CALEClientTerminate();
+}
+
+CAResult_t  CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const uint8_t  *data,
+                                                uint32_t dataLen, CALETransferType_t type,
+                                                int32_t position)
+{
+    OIC_LOG(DEBUG, TAG, "call CALEClientSendUnicastMessage");
+    VERIFY_NON_NULL(data, TAG, "data is null");
+    VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
+
+    if (LE_UNICAST != type || position < 0)
+    {
+        OIC_LOG(ERROR, TAG, "this request is not unicast");
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    return CALEClientSendUnicastMessage(remoteAddress, data, dataLen);
+}
+
+CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
+{
+    OIC_LOG(DEBUG, TAG, "call CALEClientSendMulticastMessage");
+    VERIFY_NON_NULL(data, TAG, "data is null");
+
+    return CALEClientSendMulticastMessage(data, dataLen);
+}
+
+void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
+{
+    ca_mutex_lock(g_bleReqRespClientCbMutex);
+    g_CABLEClientDataReceivedCallback = callback;
+    ca_mutex_unlock(g_bleReqRespClientCbMutex);
+}
+
+void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
+{
+    g_threadPoolHandle = handle;
+}
+
+CAResult_t CAGetLEAddress(char **local_address)
+{
+    VERIFY_NON_NULL(local_address, TAG, "local_address");
+    OIC_LOG(INFO, TAG, "CAGetLEAddress is not support");
+    return CA_NOT_SUPPORTED;
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env, jobject obj,
+                                                                    jobject callback)
+{
+    OIC_LOG(DEBUG, TAG, "CaLeRegisterLeScanCallback");
+    VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+    VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
+    VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
+
+    g_leScanCallback = (*env)->NewGlobalRef(env, callback);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, jobject obj,
+                                                                  jobject callback)
+{
+    OIC_LOG(DEBUG, TAG, "CaLeRegisterGattCallback");
+    VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+    VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
+    VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
+
+    g_leGattCallback = (*env)->NewGlobalRef(env, callback);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
+                                                          jobject device)
+{
+    VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+    VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
+    VERIFY_NON_NULL_VOID(device, TAG, "device is null");
+
+    CAResult_t res = CALEClientAddScanDeviceToList(env, device);
+    if (CA_STATUS_OK != res)
+    {
+        OIC_LOG_V(ERROR, TAG, "CALEClientAddScanDeviceToList has failed : %d", res);
+    }
+}
+
+/*
+ * Class:     org_iotivity_ca_jar_caleinterface
+ * Method:    CALeGattConnectionStateChangeCallback
+ * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(JNIEnv *env,
+                                                                                jobject obj,
+                                                                                jobject gatt,
+                                                                                jint status,
+                                                                                jint newstate)
+{
+    OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status,
+            newstate);
+    VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+    VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
+    VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
+
+    jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
+    jint state_disconnected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_DISCONNECTED");
+    jint gatt_success = CALEGetConstantsValue(env, CLASSPATH_BT_GATT, "GATT_SUCCESS");
+
+    if (gatt_success == status && state_connected == newstate) // le connected
+    {
+        jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
+        if (!jni_address)
+        {
+            goto error_exit;
+        }
+
+        const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+        if (address)
+        {
+            CAResult_t res = CALEClientUpdateDeviceState(address, STATE_CONNECTED,
+                                                         STATE_CHARACTER_NO_CHANGE,
+                                                         STATE_SEND_NONE);
+            if (CA_STATUS_OK != res)
+            {
+                OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
+                (*env)->ReleaseStringUTFChars(env, jni_address, address);
+                goto error_exit;
+            }
+            OIC_LOG_V(INFO, TAG, "ConnectionStateCB - remote address : %s", address);
+
+            (*env)->ReleaseStringUTFChars(env, jni_address, address);
+        }
+
+        CAResult_t res = CALEClientAddGattobjToList(env, gatt);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
+            goto error_exit;
+        }
+
+        res = CALEClientDiscoverServices(env, gatt);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "CALEClientDiscoverServices has failed");
+            goto error_exit;
+        }
+    }
+    else if (GATT_ERROR == status && state_disconnected == newstate)
+    {
+        OIC_LOG(INFO, TAG, "Background connection running.. please wait");
+    }
+    else // le disconnected
+    {
+        CAResult_t res = CALEClientStartScan();
+        if (CA_STATUS_OK != res)
+        {
+            if (CA_ADAPTER_NOT_ENABLED == res)
+            {
+                // scan will be started with start server when adapter is enabled
+                OIC_LOG(INFO, TAG, "Adapter was disabled");
+            }
+            else
+            {
+                OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
+                goto error_exit;
+            }
+        }
+
+        jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
+        if (!jni_address)
+        {
+            OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGattObj has failed");
+            goto error_exit;
+        }
+
+        const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+        if (address)
+        {
+            CAResult_t res = CALEClientUpdateDeviceState(address, STATE_DISCONNECTED,
+                                                                  STATE_CHARACTER_UNSET,
+                                                                  STATE_SEND_NONE);
+            if (CA_STATUS_OK != res)
+            {
+                OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
+                (*env)->ReleaseStringUTFChars(env, jni_address, address);
+                goto error_exit;
+            }
+            OIC_LOG_V(INFO, TAG, "ConnectionStateCB - remote address : %s", address);
+
+            (*env)->ReleaseStringUTFChars(env, jni_address, address);
+        }
+
+        res = CALEClientGattClose(env, gatt);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
+        }
+
+        if (g_sendBuffer)
+        {
+            (*env)->DeleteGlobalRef(env, g_sendBuffer);
+            g_sendBuffer = NULL;
+        }
+    }
+    return;
+
+    // error label.
+error_exit:
+
+    CALEClientSendFinish(env, gatt);
+    return;
+}
+
+/*
+ * Class:     org_iotivity_ca_jar_caleinterface
+ * Method:    CALeGattServicesDiscoveredCallback
+ * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIEnv *env,
+                                                                             jobject obj,
+                                                                             jobject gatt,
+                                                                             jint status)
+{
+    OIC_LOG_V(DEBUG, TAG, "CALeGattServicesDiscoveredCallback - status %d: ", status);
+    VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+    VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
+    VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
+
+    if (0 != status) // discovery error
+    {
+        CALEClientSendFinish(env, gatt);
+        return;
+    }
+
+    jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
+    if (!jni_address)
+    {
+        CALEClientSendFinish(env, gatt);
+        return;
+    }
+
+    const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+    if (!address)
+    {
+        CALEClientSendFinish(env, gatt);
+        return;
+    }
+
+    if (!CALEClientIsSetCharacteristic(address))
+    {
+        jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
+        if (!jni_uuid)
+        {
+            OIC_LOG(ERROR, TAG, "jni_uuid is null");
+            goto error_exit;
+        }
+
+        jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, gatt, jni_uuid);
+        if (!jni_obj_GattCharacteristic)
+        {
+            OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
+            goto error_exit;
+        }
+
+        CAResult_t res = CALEClientSetCharacteristicNotification(env, gatt,
+                                                                 jni_obj_GattCharacteristic);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "CALEClientSetCharacteristicNotification has failed");
+            goto error_exit;
+        }
+
+        res = CALEClientSetUUIDToDescriptor(env, gatt, jni_obj_GattCharacteristic);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG_V(INFO, TAG, "Descriptor is not found : %d", res);
+            if (g_sendBuffer)
+            {
+                CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
+                if (CA_STATUS_OK != res)
+                {
+                    OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
+                    goto error_exit;
+                }
+            }
+        }
+
+        res = CALEClientUpdateDeviceState(address, STATE_CONNECTED, STATE_CHARACTER_SET,
+                                          STATE_SEND_NONE);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
+            goto error_exit;
+        }
+    }
+    else
+    {
+        CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
+            goto error_exit;
+        }
+    }
+    OIC_LOG(INFO, TAG, "ServicesDiscovery is successful");
+    (*env)->ReleaseStringUTFChars(env, jni_address, address);
+    return;
+
+    // error label.
+error_exit:
+    OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
+    (*env)->ReleaseStringUTFChars(env, jni_address, address);
+    CALEClientSendFinish(env, gatt);
+    return;
+}
+
+/*
+ * Class:     org_iotivity_ca_jar_caleinterface
+ * Method:    CALeGattCharacteristicWritjclasseCallback
+ * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback(
+        JNIEnv *env, jobject obj, jobject gatt, jbyteArray data,
+        jint status)
+{
+    OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicWriteCallback - status : %d", status);
+    VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+    VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
+    VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
+
+    jboolean isCopy;
+    char* wroteData = (char*) (*env)->GetByteArrayElements(env, data, &isCopy);
+
+    OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicWriteCallback - write data : %s", wroteData);
+
+    // send success & signal
+    jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
+    if (!jni_address)
+    {
+        goto error_exit;
+    }
+
+    const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+    if (!address)
+    {
+        goto error_exit;
+    }
+
+    jint gatt_success = CALEGetConstantsValue(env, CLASSPATH_BT_GATT, "GATT_SUCCESS");
+    if (gatt_success != status) // error case
+    {
+        OIC_LOG(ERROR, TAG, "send failure");
+
+        // retry to write
+        CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "WriteCharacteristic has failed");
+            ca_mutex_lock(g_threadWriteCharacteristicMutex);
+            g_isSignalSetFlag = true;
+            ca_cond_signal(g_threadWriteCharacteristicCond);
+            ca_mutex_unlock(g_threadWriteCharacteristicMutex);
+
+            CAResult_t res = CALEClientUpdateDeviceState(address, STATE_CONNECTED,
+                                                         STATE_CHARACTER_SET,
+                                                         STATE_SEND_FAILED);
+            if (CA_STATUS_OK != res)
+            {
+                OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
+            }
+
+            if (g_clientErrorCallback)
+            {
+                jint length = (*env)->GetArrayLength(env, data);
+                g_clientErrorCallback(address, data, length, CA_SEND_FAILED);
+            }
+
+            CALEClientSendFinish(env, gatt);
+            goto error_exit;
+        }
+    }
+    else
+    {
+        OIC_LOG(DEBUG, TAG, "send success");
+        CAResult_t res = CALEClientUpdateDeviceState(address, STATE_CONNECTED, STATE_CHARACTER_SET,
+                                                     STATE_SEND_SUCCESS);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
+        }
+
+        ca_mutex_lock(g_threadWriteCharacteristicMutex);
+        OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
+        g_isSignalSetFlag = true;
+        ca_cond_signal(g_threadWriteCharacteristicCond);
+        ca_mutex_unlock(g_threadWriteCharacteristicMutex);
+
+        CALEClientUpdateSendCnt(env);
+    }
+
+    (*env)->ReleaseStringUTFChars(env, jni_address, address);
+    return;
+
+    // error label.
+error_exit:
+
+    CALEClientSendFinish(env, gatt);
+    return;
+}
+
+/*
+ * Class:     org_iotivity_ca_jar_caleinterface
+ * Method:    CALeGattCharacteristicChangedCallback
+ * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback(
+        JNIEnv *env, jobject obj, jobject gatt, jbyteArray data)
+{
+    OIC_LOG(DEBUG, TAG, "CALeGattCharacteristicChangedCallback");
+    VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+    VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
+    VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
+    VERIFY_NON_NULL_VOID(data, TAG, "data is null");
+
+    // get Byte Array and convert to uint8_t*
+    jint length = (*env)->GetArrayLength(env, data);
+
+    jboolean isCopy;
+    jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
+
+    OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - raw data received : %p",
+            jni_byte_responseData);
+
+    uint8_t* receivedData = OICMalloc(length);
+    if (!receivedData)
+    {
+        OIC_LOG(ERROR, TAG, "receivedData is null");
+        return;
+    }
+
+    memcpy(receivedData, jni_byte_responseData, length);
+    (*env)->ReleaseByteArrayElements(env, data, jni_byte_responseData, JNI_ABORT);
+
+    jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
+    if (!jni_address)
+    {
+        OIC_LOG(ERROR, TAG, "jni_address is null");
+        OICFree(receivedData);
+        return;
+    }
+
+    const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+    if (!address)
+    {
+        OIC_LOG(ERROR, TAG, "address is null");
+        OICFree(receivedData);
+        return;
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %p, %d",
+              receivedData, length);
+
+    ca_mutex_lock(g_bleServerBDAddressMutex);
+    uint32_t sentLength = 0;
+    g_CABLEClientDataReceivedCallback(address, receivedData, length,
+                                      &sentLength);
+    ca_mutex_unlock(g_bleServerBDAddressMutex);
+
+    (*env)->ReleaseStringUTFChars(env, jni_address, address);
+}
+
+/*
+ * Class:     org_iotivity_ca_jar_caleinterface
+ * Method:    CALeGattDescriptorWriteCallback
+ * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorWriteCallback(JNIEnv *env, jobject obj,
+                                                                         jobject gatt,
+                                                                         jint status)
+{
+    OIC_LOG_V(DEBUG, TAG, "CALeGattDescriptorWriteCallback - status %d: ", status);
+    VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+    VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
+    VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
+
+    jint gatt_success = CALEGetConstantsValue(env, CLASSPATH_BT_GATT, "GATT_SUCCESS");
+    if (gatt_success != status) // error
+    {
+        goto error_exit;
+    }
+
+    if (g_sendBuffer)
+    {
+        CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
+            goto error_exit;
+        }
+    }
+    return;
+
+// error label.
+error_exit:
+
+    CALEClientSendFinish(env, gatt);
+    return;
 }