Merge the 2019-08-01 SPL branch from AOSP-Partner

* security-aosp-nyc-mr2-release:
  Revert "DO NOT MERGE Separate SDP procedure from bonding state (1/2)"
  DO NOT MERGE Fix for Bluetooth connection being dropped after HCI Read Encryption Key Size
  DO NOT MERGE Separate SDP procedure from bonding state (1/2)
  DO NOT MERGE Send HCI Read Encryption Key properly
  DO NOT MERGE Fix potential OOB read in sdpu_get_len_from_type
  DO NOT MERGE Don't persist bonds using sample LTK
  DO NOT MERGE Drop Bluetooth connection with weak encryption key

Change-Id: I12dcf97029e0bddd45b8ee1f269aa4f547b47c09
diff --git a/Android.mk b/Android.mk
index 29760e4..00e8261 100644
--- a/Android.mk
+++ b/Android.mk
@@ -9,6 +9,10 @@
   bluetooth_CFLAGS += -DHAS_NO_BDROID_BUILDCFG
 endif
 
+ifeq ($(TARGET_BUILD_VARIANT),userdebug)
+bluetooth_CFLAGS += -DQLOGKIT_USERDEBUG
+endif
+
 ifneq ($(BOARD_BLUETOOTH_BDROID_HCILP_INCLUDED),)
   bluetooth_CFLAGS += -DHCILP_INCLUDED=$(BOARD_BLUETOOTH_BDROID_HCILP_INCLUDED)
 endif
@@ -17,6 +21,12 @@
 bluetooth_CFLAGS += -DBLUEDROID_DEBUG
 endif
 
+bluetooth_CFLAGS += -DUSE_AUDIO_TRACK
+
+ifeq ($(BOARD_USES_WIPOWER),true)
+bluetooth_CFLAGS += -DWIPOWER_SUPPORTED
+endif
+
 bluetooth_CFLAGS += -DEXPORT_SYMBOL="__attribute__((visibility(\"default\")))"
 
 #
@@ -41,6 +51,12 @@
   -UNDEBUG \
   -DLOG_NDEBUG=1
 
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_SPLIT_A2DP)),true)
+bluetooth_CFLAGS += -DBTA_AV_SPLIT_A2DP_ENABLED
+bluetooth_CFLAGS += -DBTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
+bluetooth_CFLAGS += -DAPTX_48000
+endif
+
 bluetooth_CONLYFLAGS += -std=c99
 bluetooth_CPPFLAGS :=
 
diff --git a/audio_a2dp_hw/Android.mk b/audio_a2dp_hw/Android.mk
index 0dc1388..7581068 100644
--- a/audio_a2dp_hw/Android.mk
+++ b/audio_a2dp_hw/Android.mk
@@ -12,6 +12,7 @@
 	$(LOCAL_PATH)/../ \
 	$(LOCAL_PATH)/../utils/include
 
+LOCAL_CFLAGS = -DBT_HOST_IPC_ENABLED
 LOCAL_MODULE := audio.a2dp.default
 LOCAL_MODULE_RELATIVE_PATH := hw
 
@@ -25,3 +26,24 @@
 LOCAL_CPPFLAGS += $(bluetooth_CPPFLAGS)
 
 include $(BUILD_SHARED_LIBRARY)
+
+##########################################
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := bthost_ipc.c
+
+LOCAL_C_INCLUDES += \
+	$(LOCAL_PATH)/bthost_ipc.h \
+	$(LOCAL_PATH)/../ \
+	$(LOCAL_PATH)/../utils/include
+
+LOCAL_CFLAGS = $(bdroid_CFLAGS)
+
+LOCAL_MODULE := libbthost_if
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_STATIC_LIBRARIES := libosi
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/audio_a2dp_hw/audio_a2dp_hw.c b/audio_a2dp_hw/audio_a2dp_hw.c
index fdd05e4..e901c26 100644
--- a/audio_a2dp_hw/audio_a2dp_hw.c
+++ b/audio_a2dp_hw/audio_a2dp_hw.c
@@ -1,5 +1,9 @@
 /******************************************************************************
+ *  Copyright (C) 2016, The Linux Foundation. All rights reserved.
  *
+ *  Not a Contribution
+ ******************************************************************************/
+/*****************************************************************************
  *  Copyright (C) 2009-2012 Broadcom Corporation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
@@ -23,6 +27,12 @@
  *  Description:   Implements hal for bluedroid a2dp audio device
  *
  *****************************************************************************/
+//#define BT_AUDIO_SYSTRACE_LOG
+
+#ifdef BT_AUDIO_SYSTRACE_LOG
+#define ATRACE_TAG ATRACE_TAG_ALWAYS
+#define PERF_SYSTRACE 1
+#endif
 
 #define LOG_TAG "bt_a2dp_hw"
 
@@ -50,6 +60,23 @@
 #include "osi/include/osi.h"
 #include "osi/include/socket_utils/sockets.h"
 
+#include <dlfcn.h>
+
+#ifdef BT_HOST_IPC_ENABLED
+#include "bthost_ipc.h"
+#endif
+
+#ifdef BT_AUDIO_SYSTRACE_LOG
+#include <cutils/trace.h>
+#endif
+
+//#define BT_AUDIO_SAMPLE_LOG
+
+#ifdef BT_AUDIO_SAMPLE_LOG
+FILE *outputpcmsamplefile;
+char btoutputfilename [50] = "/data/audio/output_sample";
+static int number =0;
+#endif
 /*****************************************************************************
 **  Constants & Macros
 ******************************************************************************/
@@ -71,20 +98,10 @@
 #define ERROR(fmt, ...)     LOG_ERROR(LOG_TAG, "%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
 
 #define ASSERTC(cond, msg, val) if (!(cond)) {ERROR("### ASSERT : %s line %d %s (%d) ###", __FILE__, __LINE__, msg, val);}
-
+//#define BT_HOST_IPC_PATH "/system/lib/hw/bthost-ipc.so"
 /*****************************************************************************
 **  Local type definitions
 ******************************************************************************/
-
-typedef enum {
-    AUDIO_A2DP_STATE_STARTING,
-    AUDIO_A2DP_STATE_STARTED,
-    AUDIO_A2DP_STATE_STOPPING,
-    AUDIO_A2DP_STATE_STOPPED,
-    AUDIO_A2DP_STATE_SUSPENDED, /* need explicit set param call to resume (suspend=false) */
-    AUDIO_A2DP_STATE_STANDBY    /* allows write to autoresume */
-} a2dp_state_t;
-
 struct a2dp_stream_in;
 struct a2dp_stream_out;
 
@@ -94,23 +111,6 @@
     struct a2dp_stream_out *output;
 };
 
-struct a2dp_config {
-    uint32_t                rate;
-    uint32_t                channel_flags;
-    int                     format;
-};
-
-/* move ctrl_fd outside output stream and keep open until HAL unloaded ? */
-
-struct a2dp_stream_common {
-    pthread_mutex_t         lock;
-    int                     ctrl_fd;
-    int                     audio_fd;
-    size_t                  buffer_sz;
-    struct a2dp_config      cfg;
-    a2dp_state_t            state;
-};
-
 struct a2dp_stream_out {
     struct audio_stream_out stream;
     struct a2dp_stream_common common;
@@ -126,7 +126,10 @@
 /*****************************************************************************
 **  Static variables
 ******************************************************************************/
-
+#ifdef BT_HOST_IPC_ENABLED
+static void *lib_handle = NULL;
+bt_host_ipc_interface_t *ipc_if = NULL;
+#endif
 /*****************************************************************************
 **  Static functions
 ******************************************************************************/
@@ -142,8 +145,9 @@
 ******************************************************************************/
 /* Function used only in debug mode */
 static const char* dump_a2dp_ctrl_event(char event) __attribute__ ((unused));
+#ifndef BT_HOST_IPC_ENABLED
 static void a2dp_open_ctrl_path(struct a2dp_stream_common *common);
-
+#endif
 /*****************************************************************************
 **   Miscellaneous helper functions
 ******************************************************************************/
@@ -157,11 +161,45 @@
         CASE_RETURN_STR(A2DP_CTRL_CMD_START)
         CASE_RETURN_STR(A2DP_CTRL_CMD_STOP)
         CASE_RETURN_STR(A2DP_CTRL_CMD_SUSPEND)
+        CASE_RETURN_STR(A2DP_CTRL_CMD_CHECK_STREAM_STARTED)
+        CASE_RETURN_STR(A2DP_CTRL_CMD_OFFLOAD_SUPPORTED)
+        CASE_RETURN_STR(A2DP_CTRL_CMD_OFFLOAD_NOT_SUPPORTED)
         default:
             return "UNKNOWN MSG ID";
     }
 }
 
+static int calc_audiotime(struct a2dp_config cfg, int bytes)
+{
+    int chan_count = popcount(cfg.channel_flags);
+    int bytes_per_sample = 4;
+
+    ASSERTC(cfg.format == AUDIO_FORMAT_PCM_8_24_BIT,
+            "unsupported sample sz", cfg.format);
+
+    return (int)(((int64_t)bytes * (1000000 / (chan_count * bytes_per_sample))) / cfg.rate);
+}
+
+static void ts_error_log(char *tag, int val, int buff_size, struct a2dp_config cfg)
+{
+    struct timespec now;
+    static struct timespec prev = {0,0};
+    unsigned long long now_us;
+    unsigned long long diff_us;
+
+    clock_gettime(CLOCK_MONOTONIC, &now);
+
+    now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000;
+
+    diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000;
+    prev = now;
+    if(diff_us > (unsigned long long)(calc_audiotime (cfg, buff_size) + 10000L))
+    {
+       ERROR("[%s] ts %08lld, diff %08lld, val %d %d", tag, now_us, diff_us, val, buff_size);
+    }
+}
+
+#ifndef BT_HOST_IPC_ENABLED
 /* logs timestamp with microsec precision
    pprev is optional in case a dedicated diff is required */
 static void ts_log(char *tag, int val, struct timespec *pprev_opt)
@@ -191,16 +229,23 @@
     }
 }
 
-static int calc_audiotime(struct a2dp_config cfg, int bytes)
+
+static const char* dump_a2dp_hal_state(int event)
 {
-    int chan_count = popcount(cfg.channel_flags);
-
-    ASSERTC(cfg.format == AUDIO_FORMAT_PCM_16_BIT,
-            "unsupported sample sz", cfg.format);
-
-    return (int)(((int64_t)bytes * (1000000 / (chan_count * 2))) / cfg.rate);
+    switch(event)
+    {
+        CASE_RETURN_STR(AUDIO_A2DP_STATE_STARTING)
+        CASE_RETURN_STR(AUDIO_A2DP_STATE_STARTED)
+        CASE_RETURN_STR(AUDIO_A2DP_STATE_STOPPING)
+        CASE_RETURN_STR(AUDIO_A2DP_STATE_STOPPED)
+        CASE_RETURN_STR(AUDIO_A2DP_STATE_SUSPENDED)
+        CASE_RETURN_STR(AUDIO_A2DP_STATE_STANDBY)
+        default:
+            return "UNKNOWN STATE ID";
+    }
 }
 
+//#ifndef BT_HOST_IPC_ENABLED
 /*****************************************************************************
 **
 **   bluedroid stack adaptation
@@ -365,7 +410,7 @@
 {
     char ack;
 
-    DEBUG("A2DP COMMAND %s", dump_a2dp_ctrl_event(cmd));
+    INFO("A2DP COMMAND %s", dump_a2dp_ctrl_event(cmd));
 
     if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) {
         INFO("recovering from previous error");
@@ -393,7 +438,7 @@
         return -1;
     }
 
-    DEBUG("A2DP COMMAND %s DONE STATUS %d", dump_a2dp_ctrl_event(cmd), ack);
+    INFO("A2DP COMMAND %s DONE STATUS %d", dump_a2dp_ctrl_event(cmd), ack);
 
     if (ack == A2DP_CTRL_ACK_INCALL_FAILURE)
         return ack;
@@ -407,6 +452,7 @@
 
 static int check_a2dp_ready(struct a2dp_stream_common *common)
 {
+    INFO("state %s", dump_a2dp_hal_state(common->state));
     if (a2dp_command(common, A2DP_CTRL_CMD_CHECK_READY) < 0)
     {
         ERROR("check a2dp ready failed");
@@ -493,10 +539,31 @@
 {
     INFO("state %d", common->state);
 
+    #ifdef BT_AUDIO_SYSTRACE_LOG
+    char trace_buf[512];
+    #endif
+
+    INFO("state %s", dump_a2dp_hal_state(common->state));
+
     int oldstate = common->state;
     common->state = AUDIO_A2DP_STATE_STARTING;
 
     int a2dp_status = a2dp_command(common, A2DP_CTRL_CMD_START);
+    #ifdef BT_AUDIO_SYSTRACE_LOG
+    snprintf(trace_buf, 32, "start_audio_data_path:");
+    if (PERF_SYSTRACE)
+    {
+        ATRACE_BEGIN(trace_buf);
+    }
+    #endif
+
+
+    #ifdef BT_AUDIO_SYSTRACE_LOG
+    if (PERF_SYSTRACE)
+    {
+        ATRACE_END();
+    }
+    #endif
     if (a2dp_status < 0)
     {
         ERROR("Audiopath start failed (status %d)", a2dp_status);
@@ -508,6 +575,7 @@
         goto error;
     }
 
+#ifndef BTA_AV_SPLIT_A2DP_ENABLED
     /* connect socket if not yet connected */
     if (common->audio_fd == AUDIO_SKT_DISCONNECTED)
     {
@@ -517,8 +585,11 @@
             ERROR("Audiopath start failed - error opening data socket");
             goto error;
         }
+        common->state = AUDIO_A2DP_STATE_STARTED;
     }
+#else
     common->state = AUDIO_A2DP_STATE_STARTED;
+#endif
     return 0;
 
 error:
@@ -530,7 +601,7 @@
 {
     int oldstate = common->state;
 
-    INFO("state %d", common->state);
+    INFO("state %s", dump_a2dp_hal_state(common->state));
 
     /* prevent any stray output writes from autostarting the stream
        while stopping audiopath */
@@ -545,16 +616,18 @@
 
     common->state = AUDIO_A2DP_STATE_STOPPED;
 
+#ifndef BTA_AV_SPLIT_A2DP_ENABLED
     /* disconnect audio path */
     skt_disconnect(common->audio_fd);
     common->audio_fd = AUDIO_SKT_DISCONNECTED;
+#endif
 
     return 0;
 }
 
 static int suspend_audio_datapath(struct a2dp_stream_common *common, bool standby)
 {
-    INFO("state %d", common->state);
+    INFO("state %s", dump_a2dp_hal_state(common->state));
 
     if (common->state == AUDIO_A2DP_STATE_STOPPING)
         return -1;
@@ -567,15 +640,28 @@
     else
         common->state = AUDIO_A2DP_STATE_SUSPENDED;
 
+#ifndef BTA_AV_SPLIT_A2DP_ENABLED
     /* disconnect audio path */
     skt_disconnect(common->audio_fd);
 
     common->audio_fd = AUDIO_SKT_DISCONNECTED;
+#endif
 
     return 0;
 }
 
 
+static int check_a2dp_stream_started(struct a2dp_stream_out *out)
+{
+   if (a2dp_command(&out->common, A2DP_CTRL_CMD_CHECK_STREAM_STARTED) < 0)
+   {
+       INFO("Btif not in stream state");
+       return -1;
+   }
+   return 0;
+}
+#endif
+
 /*****************************************************************************
 **
 **  audio output callbacks
@@ -587,6 +673,9 @@
 {
     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
     int sent = -1;
+    #ifdef BT_AUDIO_SYSTRACE_LOG
+    char trace_buf[512];
+    #endif
 
     DEBUG("write %zu bytes (fd %d)", bytes, out->common.audio_fd);
 
@@ -601,7 +690,11 @@
     if ((out->common.state == AUDIO_A2DP_STATE_STOPPED) ||
         (out->common.state == AUDIO_A2DP_STATE_STANDBY))
     {
+#ifdef BT_HOST_IPC_ENABLED
+        if (ipc_if->start_audio_datapath(&out->common) < 0)
+#else
         if (start_audio_datapath(&out->common) < 0)
+#endif
         {
             goto finish;
         }
@@ -611,13 +704,46 @@
         ERROR("stream not in stopped or standby");
         goto finish;
     }
+    #ifdef BT_AUDIO_SAMPLE_LOG
+    if (outputpcmsamplefile)
+    {
+        fwrite (buffer,1,bytes,outputpcmsamplefile);
+    }
+    #endif
+
+    ts_error_log("a2dp_out_write", bytes, out->common.buffer_sz, out->common.cfg);
 
     pthread_mutex_unlock(&out->common.lock);
+
+    #ifdef BT_AUDIO_SYSTRACE_LOG
+    snprintf(trace_buf, 32, "out_write:");
+    if (PERF_SYSTRACE)
+    {
+        ATRACE_BEGIN(trace_buf);
+    }
+    #endif
+
+#ifdef BT_HOST_IPC_ENABLED
+    sent = ipc_if->skt_write(out->common.audio_fd, buffer,  bytes);
+#else
     sent = skt_write(out->common.audio_fd, buffer,  bytes);
+#endif
     pthread_mutex_lock(&out->common.lock);
 
-    if (sent == -1) {
+    #ifdef BT_AUDIO_SYSTRACE_LOG
+    if (PERF_SYSTRACE)
+    {
+        ATRACE_END();
+    }
+    #endif
+
+    if (sent == -1)
+    {
+#ifdef BT_HOST_IPC_ENABLED
+        ipc_if->skt_disconnect(out->common.audio_fd);
+#else
         skt_disconnect(out->common.audio_fd);
+#endif
         out->common.audio_fd = AUDIO_SKT_DISCONNECTED;
         if ((out->common.state != AUDIO_A2DP_STATE_SUSPENDED) &&
                 (out->common.state != AUDIO_A2DP_STATE_STOPPING)) {
@@ -647,7 +773,7 @@
 {
     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
 
-    DEBUG("rate %" PRIu32,out->common.cfg.rate);
+    INFO("rate %" PRIu32,out->common.cfg.rate);
 
     return out->common.cfg.rate;
 }
@@ -656,7 +782,7 @@
 {
     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
 
-    DEBUG("out_set_sample_rate : %" PRIu32, rate);
+    INFO("out_set_sample_rate : %" PRIu32, rate);
 
     if (rate != AUDIO_STREAM_DEFAULT_RATE)
     {
@@ -676,7 +802,7 @@
     const size_t period_size = out->common.buffer_sz / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS;
     const size_t mixer_unit_size = 16 /* frames */ * 4 /* framesize */;
 
-    DEBUG("socket buffer size: %zu  period size: %zu", out->common.buffer_sz, period_size);
+    INFO("socket buffer size: %zu  period size: %zu", out->common.buffer_sz, period_size);
     if (period_size % mixer_unit_size != 0) {
         ERROR("period size %zu not a multiple of %zu", period_size, mixer_unit_size);
     }
@@ -688,7 +814,7 @@
 {
     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
 
-    DEBUG("channels 0x%" PRIx32, out->common.cfg.channel_flags);
+    INFO("channels 0x%" PRIx32, out->common.cfg.channel_flags);
 
     return out->common.cfg.channel_flags;
 }
@@ -696,7 +822,7 @@
 static audio_format_t out_get_format(const struct audio_stream *stream)
 {
     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
-    DEBUG("format 0x%x", out->common.cfg.format);
+    INFO("format 0x%x", out->common.cfg.format);
     return out->common.cfg.format;
 }
 
@@ -704,7 +830,7 @@
 {
     UNUSED(stream);
     UNUSED(format);
-    DEBUG("setting format not yet supported (0x%x)", format);
+    INFO("setting format not yet supported (0x%x)", format);
     return -ENOSYS;
 }
 
@@ -718,7 +844,11 @@
     pthread_mutex_lock(&out->common.lock);
     // Do nothing in SUSPENDED state.
     if (out->common.state != AUDIO_A2DP_STATE_SUSPENDED)
-        retVal = suspend_audio_datapath(&out->common, true);
+#ifdef BT_HOST_IPC_ENABLED
+        retVal =  ipc_if->suspend_audio_datapath(&out->common, true);
+#else
+        retVal =  suspend_audio_datapath(&out->common, true);
+#endif
     out->frames_rendered = 0; // rendered is reset, presented is not
     pthread_mutex_unlock (&out->common.lock);
 
@@ -737,45 +867,129 @@
 {
     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
 
-    INFO("state %d", out->common.state);
+    INFO("out_set_parameters: state %d", out->common.state);
 
     hash_map_t *params = hash_map_utils_new_from_string_params(kvpairs);
     int status = 0;
-
+    char *keyval;
     if (!params)
       return status;
 
-    pthread_mutex_lock(&out->common.lock);
-
     /* dump params */
     hash_map_utils_dump_string_keys_string_values(params);
 
-    char *keyval = (char *)hash_map_get(params, "closing");
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+    keyval = (char *)hash_map_get(params, "A2dpStarted");
+
+    if (keyval != NULL)
+    {
+        INFO("out_set_parameters, param: A2dpStarted");
+        if (strcmp(keyval, "true") == 0)
+        {
+            INFO("out_set_parameters, value: true");
+            pthread_mutex_lock(&out->common.lock);
+            if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED)
+            {
+                INFO("stream suspended");
+                status = -1;
+            }
+            else if ((out->common.state == AUDIO_A2DP_STATE_STOPPED) ||
+                (out->common.state == AUDIO_A2DP_STATE_STANDBY))
+            {
+#ifdef BT_HOST_IPC_ENABLED
+                if (ipc_if->start_audio_datapath(&out->common) < 0)
+#else
+                if (start_audio_datapath(&out->common) < 0)
+#endif
+                {
+                    INFO("stream start failed");
+                    status = -1;
+                }
+            }
+            else if (out->common.state != AUDIO_A2DP_STATE_STARTED)
+            {
+                ERROR("stream not in stopped or standby");
+                status = -1;
+            }
+            pthread_mutex_unlock(&out->common.lock);
+            INFO("stream start completes with status: %d", status);
+        }
+        else if (strcmp(keyval, "false") == 0)
+        {
+            INFO("out_set_parameters, value: false");
+            pthread_mutex_lock(&out->common.lock);
+            if (out->common.state != AUDIO_A2DP_STATE_SUSPENDED)
+#ifdef BT_HOST_IPC_ENABLED
+                status = ipc_if->suspend_audio_datapath(&out->common, true);
+#else
+                status = suspend_audio_datapath(&out->common, true);
+#endif
+            else
+            {
+                ERROR("stream alreday suspended");
+            }
+            pthread_mutex_unlock(&out->common.lock);
+            INFO("stream stop completes with status: %d", status);
+        }
+    }
+#endif
+
+    keyval = (char *)hash_map_get(params, "closing");
 
     if (keyval && strcmp(keyval, "true") == 0)
     {
         DEBUG("stream closing, disallow any writes");
+            pthread_mutex_lock(&out->common.lock);
         out->common.state = AUDIO_A2DP_STATE_STOPPING;
+            pthread_mutex_unlock(&out->common.lock);
     }
 
     keyval = (char *)hash_map_get(params, "A2dpSuspended");
 
-    if (keyval && strcmp(keyval, "true") == 0)
+    if (keyval)
     {
-        if (out->common.state == AUDIO_A2DP_STATE_STARTED)
-            status = suspend_audio_datapath(&out->common, false);
-    }
-    else
-    {
-        /* Do not start the streaming automatically. If the phone was streaming
-         * prior to being suspended, the next out_write shall trigger the
-         * AVDTP start procedure */
-        if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED)
-            out->common.state = AUDIO_A2DP_STATE_STANDBY;
-        /* Irrespective of the state, return 0 */
+        if (strcmp(keyval, "true") == 0) 
+        {
+            pthread_mutex_lock(&out->common.lock);
+            if (out->common.state == AUDIO_A2DP_STATE_STARTED)
+#ifdef BT_HOST_IPC_ENABLED
+                status = ipc_if->suspend_audio_datapath(&out->common, false);
+#else
+                status = suspend_audio_datapath(&out->common, false);
+#endif
+            else
+            {
+#ifdef BT_HOST_IPC_ENABLED
+                if (ipc_if->check_a2dp_stream_started(&out->common) == 0)
+#else
+                if (check_a2dp_stream_started(out) == 0)
+#endif
+                   /*Btif and A2dp HAL state can be out of sync
+                    *check state of btif and suspend audio.
+                    *Happens when remote initiates start.*/
+#ifdef BT_HOST_IPC_ENABLED
+                    status = ipc_if->suspend_audio_datapath(&out->common, false);
+#else
+                    status = suspend_audio_datapath(&out->common, false);
+#endif
+                else
+                    out->common.state = AUDIO_A2DP_STATE_SUSPENDED;
+            }
+            pthread_mutex_unlock(&out->common.lock);
+        }
+        else
+        {
+            pthread_mutex_lock(&out->common.lock);
+            /* Do not start the streaming automatically. If the phone was streaming
+             * prior to being suspended, the next out_write shall trigger the
+             * AVDTP start procedure */
+            if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED)
+                out->common.state = AUDIO_A2DP_STATE_STANDBY;
+            /* Irrespective of the state, return 0 */
+            pthread_mutex_unlock(&out->common.lock);
+        }
     }
 
-    pthread_mutex_unlock(&out->common.lock);
     hash_map_free(params);
 
     return status;
@@ -1007,7 +1221,11 @@
     if ((in->common.state == AUDIO_A2DP_STATE_STOPPED) ||
         (in->common.state == AUDIO_A2DP_STATE_STANDBY))
     {
+#ifdef BT_HOST_IPC_ENABLED
+        if (ipc_if->start_audio_datapath(&in->common) < 0)
+#else
         if (start_audio_datapath(&in->common) < 0)
+#endif
         {
             goto error;
         }
@@ -1019,11 +1237,20 @@
     }
 
     pthread_mutex_unlock(&in->common.lock);
+#ifdef BT_HOST_IPC_ENABLED
+    read = ipc_if->skt_read(in->common.audio_fd, buffer, bytes);
+#else
     read = skt_read(in->common.audio_fd, buffer, bytes);
+#endif
     pthread_mutex_lock(&in->common.lock);
+
     if (read == -1)
     {
+#ifdef BT_HOST_IPC_ENABLED
+        ipc_if->skt_disconnect(in->common.audio_fd);
+#else
         skt_disconnect(in->common.audio_fd);
+#endif
         in->common.audio_fd = AUDIO_SKT_DISCONNECTED;
         if ((in->common.state != AUDIO_A2DP_STATE_SUSPENDED) &&
                 (in->common.state != AUDIO_A2DP_STATE_STOPPING)) {
@@ -1102,7 +1329,31 @@
 
     if (!out)
         return -ENOMEM;
+    #ifdef BT_AUDIO_SAMPLE_LOG
+    snprintf(btoutputfilename, sizeof(btoutputfilename), "%s%d%s", btoutputfilename, number,".pcm");
+    outputpcmsamplefile = fopen (btoutputfilename, "ab");
+    number++;
+    #endif
 
+#ifdef BT_HOST_IPC_ENABLED
+    lib_handle = dlopen("libbthost_if.so", RTLD_NOW);
+    if (!lib_handle)
+    {
+        INFO("Failed to load bthost-ipc library %s",dlerror());
+        ret = -1;
+        goto err_open;
+    }
+    else
+    {
+        ipc_if = (bt_host_ipc_interface_t*) dlsym(lib_handle,"BTHOST_IPC_INTERFACE");
+        if (!ipc_if)
+        {
+            ERROR("Failed to load BT IPC library symbol");
+            ret  = -1;
+            goto err_open;
+        }
+    }
+#endif
     out->stream.common.get_sample_rate = out_get_sample_rate;
     out->stream.common.set_sample_rate = out_set_sample_rate;
     out->stream.common.get_buffer_size = out_get_buffer_size;
@@ -1123,10 +1374,13 @@
 
 
     /* initialize a2dp specifics */
+#ifdef BT_HOST_IPC_ENABLED
+    ipc_if->a2dp_stream_common_init(&out->common);
+#else
     a2dp_stream_common_init(&out->common);
-
+#endif
     out->common.cfg.channel_flags = AUDIO_STREAM_DEFAULT_CHANNEL_FLAG;
-    out->common.cfg.format = AUDIO_STREAM_DEFAULT_FORMAT;
+    out->common.cfg.format = AUDIO_FORMAT_PCM_8_24_BIT;
     out->common.cfg.rate = AUDIO_STREAM_DEFAULT_RATE;
 
    /* set output config values */
@@ -1139,7 +1393,11 @@
     *stream_out = &out->stream;
     a2dp_dev->output = out;
 
+#ifdef BT_HOST_IPC_ENABLED
+    ipc_if->a2dp_open_ctrl_path(&out->common);
+#else
     a2dp_open_ctrl_path(&out->common);
+#endif
     if (out->common.ctrl_fd == AUDIO_SKT_DISCONNECTED)
     {
         ERROR("ctrl socket failed to connect (%s)", strerror(errno));
@@ -1147,10 +1405,17 @@
         goto err_open;
     }
 
-    DEBUG("success");
+#ifdef BT_HOST_IPC_ENABLED
+    if (ipc_if->a2dp_command(&out->common, A2DP_CTRL_CMD_OFFLOAD_NOT_SUPPORTED) == 0) {
+#else
+    if (a2dp_command(&out->common, A2DP_CTRL_CMD_OFFLOAD_NOT_SUPPORTED) == 0) {
+#endif
+        DEBUG("Streaming mode set successfully");
+    }
+    INFO("success");
     /* Delay to ensure Headset is in proper state when START is initiated
        from DUT immediately after the connection due to ongoing music playback. */
-    usleep(250000);
+    usleep(1000000);
     return 0;
 
 err_open:
@@ -1171,17 +1436,31 @@
 
     pthread_mutex_lock(&out->common.lock);
     if ((out->common.state == AUDIO_A2DP_STATE_STARTED) ||
-            (out->common.state == AUDIO_A2DP_STATE_STOPPING)) {
+            (out->common.state == AUDIO_A2DP_STATE_STOPPING))
+#ifdef BT_HOST_IPC_ENABLED
+        ipc_if->stop_audio_datapath(&out->common);
+#else
         stop_audio_datapath(&out->common);
-    }
+#endif
 
+    #ifdef BT_AUDIO_SAMPLE_LOG
+    ALOGV("close file output");
+    fclose (outputpcmsamplefile);
+    #endif
+
+#ifdef BT_HOST_IPC_ENABLED
+    ipc_if->skt_disconnect(out->common.ctrl_fd);
+#else
     skt_disconnect(out->common.ctrl_fd);
+#endif
     out->common.ctrl_fd = AUDIO_SKT_DISCONNECTED;
+    if (lib_handle)
+        dlclose(lib_handle);
     free(stream);
     a2dp_dev->output = NULL;
     pthread_mutex_unlock(&out->common.lock);
 
-    DEBUG("done");
+    INFO("done");
 }
 
 static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
@@ -1193,7 +1472,7 @@
     if (out == NULL)
         return retval;
 
-    INFO("state %d", out->common.state);
+
 
     retval = out->stream.common.set_parameters((struct audio_stream *)out, kvpairs);
 
@@ -1309,6 +1588,25 @@
     if (!in)
         return -ENOMEM;
 
+#ifdef BT_HOST_IPC_ENABLED
+    lib_handle = dlopen("libbthost_if.so", RTLD_NOW);
+    if (!lib_handle)
+    {
+        INFO("Failed to load bthost-ipc library %s",dlerror());
+        ret = -1;
+        goto err_open;
+    }
+    else
+    {
+        ipc_if = (bt_host_ipc_interface_t*) dlsym(lib_handle,"BTHOST_IPC_INTERFACE");
+        if (!ipc_if)
+        {
+            ERROR("Failed to load BT IPC library symbol");
+            ret =  -1;
+            goto err_open;
+        }
+    }
+#endif
     in->stream.common.get_sample_rate = in_get_sample_rate;
     in->stream.common.set_sample_rate = in_set_sample_rate;
     in->stream.common.get_buffer_size = in_get_buffer_size;
@@ -1326,12 +1624,19 @@
     in->stream.get_input_frames_lost = in_get_input_frames_lost;
 
     /* initialize a2dp specifics */
+#ifdef BT_HOST_IPC_ENABLED
+    ipc_if->a2dp_stream_common_init(&in->common);
+#else
     a2dp_stream_common_init(&in->common);
-
+#endif
     *stream_in = &in->stream;
     a2dp_dev->input = in;
 
+#ifdef BT_HOST_IPC_ENABLED
+    ipc_if->a2dp_open_ctrl_path(&in->common);
+#else
     a2dp_open_ctrl_path(&in->common);
+#endif
     if (in->common.ctrl_fd == AUDIO_SKT_DISCONNECTED)
     {
         ERROR("ctrl socket failed to connect (%s)", strerror(errno));
@@ -1339,7 +1644,18 @@
         goto err_open;
     }
 
+#ifdef BT_HOST_IPC_ENABLED
+    if (ipc_if->a2dp_command(&in->common, A2DP_CTRL_CMD_OFFLOAD_NOT_SUPPORTED) == 0) {
+#else
+    if (a2dp_command(&in->common, A2DP_CTRL_CMD_OFFLOAD_NOT_SUPPORTED) == 0) {
+#endif
+        DEBUG("Streaming mode set successfully");
+    }
+#ifdef BT_HOST_IPC_ENABLED
+    if (ipc_if->a2dp_read_audio_config(&in->common) < 0) {
+#else
     if (a2dp_read_audio_config(&in->common) < 0) {
+#endif
         ERROR("a2dp_read_audio_config failed (%s)", strerror(errno));
         ret = -1;
         goto err_open;
@@ -1366,13 +1682,22 @@
     INFO("closing input (state %d)", state);
 
     if ((state == AUDIO_A2DP_STATE_STARTED) || (state == AUDIO_A2DP_STATE_STOPPING))
+#ifdef BT_HOST_IPC_ENABLED
+        ipc_if->stop_audio_datapath(&in->common);
+#else
         stop_audio_datapath(&in->common);
+#endif
 
+#ifdef BT_HOST_IPC_ENABLED
+    ipc_if->skt_disconnect(in->common.ctrl_fd);
+#else
     skt_disconnect(in->common.ctrl_fd);
+#endif
     in->common.ctrl_fd = AUDIO_SKT_DISCONNECTED;
     free(stream);
     a2dp_dev->input = NULL;
-
+    if (lib_handle)
+        dlclose(lib_handle);
     DEBUG("done");
 }
 
diff --git a/audio_a2dp_hw/audio_a2dp_hw.h b/audio_a2dp_hw/audio_a2dp_hw.h
index 11d438a..67fd212 100644
--- a/audio_a2dp_hw/audio_a2dp_hw.h
+++ b/audio_a2dp_hw/audio_a2dp_hw.h
@@ -1,4 +1,9 @@
 /******************************************************************************
+ *  Copyright (C) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a Contribution
+ *****************************************************************************/
+/******************************************************************************
  *
  *  Copyright (C) 2009-2012 Broadcom Corporation
  *
@@ -26,7 +31,7 @@
 
 #ifndef AUDIO_A2DP_HW_H
 #define AUDIO_A2DP_HW_H
-
+#include <pthread.h>
 /*****************************************************************************
 **  Constants & Macros
 ******************************************************************************/
@@ -35,7 +40,12 @@
 #define A2DP_CTRL_PATH "/data/misc/bluedroid/.a2dp_ctrl"
 #define A2DP_DATA_PATH "/data/misc/bluedroid/.a2dp_data"
 
+#ifndef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
 #define AUDIO_STREAM_DEFAULT_RATE          44100
+#else
+#define AUDIO_STREAM_DEFAULT_RATE          48000
+#endif
+
 #define AUDIO_STREAM_DEFAULT_FORMAT        AUDIO_FORMAT_PCM_16_BIT
 #define AUDIO_STREAM_DEFAULT_CHANNEL_FLAG  AUDIO_CHANNEL_OUT_STEREO
 
@@ -55,7 +65,7 @@
 // 20 * 512 is not sufficient size to smooth the variability for some BT devices,
 // resulting in mixer sleep and throttling. We increase this to 28 * 512 to help
 // reduce the effect of variable data consumption.
-#define AUDIO_STREAM_OUTPUT_BUFFER_SZ      (28*512)
+#define AUDIO_STREAM_OUTPUT_BUFFER_SZ     (28*1024)
 
 // AUDIO_STREAM_OUTPUT_BUFFER_PERIODS controls how the socket buffer is divided
 // for AudioFlinger data delivery. The AudioFlinger mixer delivers data in chunks
@@ -80,21 +90,52 @@
 typedef enum {
     A2DP_CTRL_CMD_NONE,
     A2DP_CTRL_CMD_CHECK_READY,
+    A2DP_CTRL_CMD_CHECK_STREAM_STARTED,
     A2DP_CTRL_CMD_START,
     A2DP_CTRL_CMD_STOP,
     A2DP_CTRL_CMD_SUSPEND,
     A2DP_CTRL_GET_AUDIO_CONFIG,
     A2DP_CTRL_CMD_OFFLOAD_START,
+    A2DP_CTRL_CMD_OFFLOAD_SUPPORTED,
+    A2DP_CTRL_CMD_OFFLOAD_NOT_SUPPORTED,
 } tA2DP_CTRL_CMD;
 
 typedef enum {
     A2DP_CTRL_ACK_SUCCESS,
     A2DP_CTRL_ACK_FAILURE,
     A2DP_CTRL_ACK_INCALL_FAILURE, /* Failure when in Call*/
+    A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS, /* Ack when Disconnection in Progress */
     A2DP_CTRL_ACK_UNSUPPORTED
 } tA2DP_CTRL_ACK;
 
 
+typedef enum {
+    AUDIO_A2DP_STATE_STARTING,
+    AUDIO_A2DP_STATE_STARTED,
+    AUDIO_A2DP_STATE_STOPPING,
+    AUDIO_A2DP_STATE_STOPPED,
+    AUDIO_A2DP_STATE_SUSPENDED, /* need explicit set param call to resume (suspend=false) */
+    AUDIO_A2DP_STATE_STANDBY    /* allows write to autoresume */
+} a2dp_state_t;
+
+struct a2dp_config {
+    uint32_t                rate;
+    uint32_t                channel_flags;
+    int                     format;
+};
+
+/* move ctrl_fd outside output stream and keep open until HAL unloaded ? */
+#define  MAX_CODEC_CFG_SIZE  30
+
+struct a2dp_stream_common {
+    pthread_mutex_t         lock;
+    int                     ctrl_fd;
+    int                     audio_fd;
+    size_t                  buffer_sz;
+    struct a2dp_config      cfg;
+    a2dp_state_t            state;
+    uint8_t                 codec_cfg[MAX_CODEC_CFG_SIZE];
+};
 /*****************************************************************************
 **  Type definitions for callback functions
 ******************************************************************************/
diff --git a/audio_a2dp_hw/bthost_ipc.c b/audio_a2dp_hw/bthost_ipc.c
new file mode 100644
index 0000000..5137e94
--- /dev/null
+++ b/audio_a2dp_hw/bthost_ipc.c
@@ -0,0 +1,1262 @@
+/******************************************************************************
+ *  Copyright (C) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a Contribution
+ *****************************************************************************/
+/*****************************************************************************
+ *  Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+/*      bthost_ipc.c
+ *
+ *  Description:   Implements IPC interface between HAL and BT host
+ *
+ *****************************************************************************/
+
+#include <errno.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/poll.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <system/audio.h>
+#include <hardware/audio.h>
+
+#include <hardware/hardware.h>
+#include "bthost_ipc.h"
+#include "bt_utils.h"
+#include "osi/include/hash_map.h"
+#include "osi/include/hash_map_utils.h"
+#include "osi/include/log.h"
+#include "osi/include/osi.h"
+#include "osi/include/socket_utils/sockets.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "bthost_ipc"
+#include "osi/include/log.h"
+
+
+static int bt_split_a2dp_enabled = 0;
+static int open_ctrl_chnl_fail_count = 0;
+/*****************************************************************************
+**  Constants & Macros
+******************************************************************************/
+/* Below two values adds up to 8 sec retry to address IOT issues*/
+#define STREAM_START_MAX_RETRY_COUNT 10
+#define STREAM_START_MAX_RETRY_LOOPER 8
+
+#define CTRL_CHAN_RETRY_COUNT 1
+#define USEC_PER_SEC 1000000L
+#define SOCK_SEND_TIMEOUT_MS 2000  /* Timeout for sending */
+#define SOCK_RECV_TIMEOUT_MS 5000  /* Timeout for receiving */
+
+// set WRITE_POLL_MS to 0 for blocking sockets, nonzero for polled non-blocking sockets
+#define WRITE_POLL_MS 20
+
+#define CASE_RETURN_STR(const) case const: return #const;
+
+#define FNLOG()             LOG_VERBOSE(LOG_TAG, "%s", __FUNCTION__);
+#define DEBUG(fmt, ...)     LOG_VERBOSE(LOG_TAG, "%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
+#define INFO(fmt, ...)      LOG_INFO(LOG_TAG, "%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
+#define WARN(fmt, ...)      LOG_WARN(LOG_TAG, "%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
+#define ERROR(fmt, ...)     LOG_ERROR(LOG_TAG, "%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
+
+#define ASSERTC(cond, msg, val) if (!(cond)) {ERROR("### ASSERT : %s line %d %s (%d) ###", __FILE__, __LINE__, msg, val);}
+
+/*****************************************************************************
+**  Local type definitions
+******************************************************************************/
+
+struct a2dp_stream_common audio_stream;
+
+/*****************************************************************************
+**  Static functions
+******************************************************************************/
+
+audio_sbc_encoder_config sbc_codec;
+audio_aptx_encoder_config aptx_codec;
+audio_aac_encoder_config aac_codec;
+/*****************************************************************************
+**  Externs
+******************************************************************************/
+
+/*****************************************************************************
+**  Functions
+******************************************************************************/
+static int check_a2dp_open_ready(struct a2dp_stream_common *common);
+void a2dp_open_ctrl_path(struct a2dp_stream_common *common);
+/*****************************************************************************
+**   Miscellaneous helper functions
+******************************************************************************/
+static const char* dump_a2dp_ctrl_event(char event)
+{
+    switch(event)
+    {
+        CASE_RETURN_STR(A2DP_CTRL_CMD_NONE)
+        CASE_RETURN_STR(A2DP_CTRL_CMD_CHECK_READY)
+        CASE_RETURN_STR(A2DP_CTRL_CMD_START)
+        CASE_RETURN_STR(A2DP_CTRL_CMD_STOP)
+        CASE_RETURN_STR(A2DP_CTRL_CMD_SUSPEND)
+        CASE_RETURN_STR(A2DP_CTRL_CMD_OFFLOAD_SUPPORTED)
+        CASE_RETURN_STR(A2DP_CTRL_CMD_OFFLOAD_NOT_SUPPORTED)
+        CASE_RETURN_STR(A2DP_CTRL_CMD_CHECK_STREAM_STARTED)
+        CASE_RETURN_STR(A2DP_CTRL_GET_CODEC_CONFIG)
+        CASE_RETURN_STR(A2DP_CTRL_GET_MULTICAST_STATUS)
+        CASE_RETURN_STR(A2DP_CTRL_GET_CONNECTION_STATUS)
+        default:
+            return "UNKNOWN MSG ID";
+    }
+}
+
+/* logs timestamp with microsec precision
+   pprev is optional in case a dedicated diff is required */
+static void ts_log(char *tag, int val, struct timespec *pprev_opt)
+{
+    struct timespec now;
+    static struct timespec prev = {0,0};
+    unsigned long long now_us;
+    unsigned long long diff_us;
+    UNUSED(tag);
+    UNUSED(val);
+
+    clock_gettime(CLOCK_MONOTONIC, &now);
+
+    now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000;
+
+    if (pprev_opt)
+    {
+        diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000;
+        *pprev_opt = now;
+        DEBUG("[%s] ts %08lld, *diff %08lld, val %d", tag, now_us, diff_us, val);
+    }
+    else
+    {
+        diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000;
+        prev = now;
+        DEBUG("[%s] ts %08lld, diff %08lld, val %d", tag, now_us, diff_us, val);
+    }
+}
+
+
+static const char* dump_a2dp_hal_state(int event)
+{
+    switch(event)
+    {
+        CASE_RETURN_STR(AUDIO_A2DP_STATE_STARTING)
+        CASE_RETURN_STR(AUDIO_A2DP_STATE_STARTED)
+        CASE_RETURN_STR(AUDIO_A2DP_STATE_STOPPING)
+        CASE_RETURN_STR(AUDIO_A2DP_STATE_STOPPED)
+        CASE_RETURN_STR(AUDIO_A2DP_STATE_SUSPENDED)
+        CASE_RETURN_STR(AUDIO_A2DP_STATE_STANDBY)
+        default:
+            return "UNKNOWN STATE ID";
+    }
+}
+static void* a2dp_codec_parser(uint8_t *codec_cfg, audio_format_t *codec_type)
+{
+    char byte,len;
+    uint8_t *p_cfg = codec_cfg;
+    INFO("%s",__func__);
+    if (codec_cfg[CODEC_OFFSET] == CODEC_TYPE_PCM)
+    {
+        *codec_type = AUDIO_FORMAT_PCM_16_BIT;
+        //For the time being Audio does not require any param to be passed for PCM so returning null
+        return NULL;
+    }
+    else if (codec_cfg[CODEC_OFFSET] == CODEC_TYPE_SBC)
+    {
+        memset(&sbc_codec,0,sizeof(audio_sbc_encoder_config));
+        p_cfg++;//skip dev idx
+        len = *p_cfg++;
+        p_cfg++;//skip media type
+        len--;
+        p_cfg++;
+        len--;
+        byte = *p_cfg++;
+        len--;
+        switch (byte & A2D_SBC_FREQ_MASK)
+        {
+            case A2D_SBC_SAMP_FREQ_48:
+                 sbc_codec.sampling_rate = 48000;
+                 break;
+            case A2D_SBC_SAMP_FREQ_44:
+                 sbc_codec.sampling_rate = 44100;
+                 break;
+            case A2D_SBC_SAMP_FREQ_32:
+                 sbc_codec.sampling_rate = 3200;
+                 break;
+            case A2D_SBC_SAMP_FREQ_16:
+                 sbc_codec.sampling_rate = 16000;
+                 break;
+            default:
+                 ERROR("Unkown sampling rate");
+        }
+
+        switch (byte & A2D_SBC_CHN_MASK)
+        {
+            case A2D_SBC_CH_MD_JOINT:
+                 sbc_codec.channels = 3;
+                 break;
+            case A2D_SBC_CH_MD_STEREO:
+                 sbc_codec.channels = 2;
+                 break;
+            case A2D_SBC_CH_MD_DUAL:
+                 sbc_codec.channels = 1;
+                 break;
+            case A2D_SBC_CH_MD_MONO:
+                 sbc_codec.channels = 0;
+                 break;
+            default:
+                 ERROR("Unknow channel mode");
+        }
+        byte = *p_cfg++;
+        len--;
+        switch (byte & A2D_SBC_BLK_MASK)
+        {
+            case A2D_SBC_BLOCKS_16:
+                sbc_codec.blk_len = 16;
+                break;
+            case A2D_SBC_BLOCKS_12:
+                sbc_codec.blk_len = 12;
+                break;
+            case A2D_SBC_BLOCKS_8:
+                sbc_codec.blk_len = 8;
+                break;
+            case A2D_SBC_BLOCKS_4:
+                sbc_codec.blk_len = 4;
+                break;
+            default:
+                ERROR("Unknown block length");
+        }
+
+        switch (byte & A2D_SBC_SUBBAND_MASK)
+        {
+            case A2D_SBC_SUBBAND_8:
+                sbc_codec.subband = 8;
+                break;
+            case A2D_SBC_SUBBAND_4:
+                sbc_codec.subband = 4;
+                break;
+            default:
+                ERROR("Unknown subband");
+        }
+        switch (byte & A2D_SBC_ALLOC_MASK)
+        {
+            case A2D_SBC_ALLOC_MD_L:
+                sbc_codec.alloc = 1;
+                break;
+            case A2D_SBC_ALLOC_MD_S:
+                sbc_codec.alloc = 2;
+            default:
+                ERROR("Unknown alloc method");
+        }
+        sbc_codec.min_bitpool = *p_cfg++;
+        len--;
+        sbc_codec.max_bitpool = *p_cfg++;
+        len--;
+        if (len == 0)
+            INFO("Copied codec config");
+
+        p_cfg += 2; //skip mtu
+        sbc_codec.bitrate = *p_cfg++;
+        sbc_codec.bitrate |= (*p_cfg++ << 8);
+        sbc_codec.bitrate |= (*p_cfg++ << 16);
+        sbc_codec.bitrate |= (*p_cfg++ << 24);
+        *codec_type = AUDIO_FORMAT_SBC;
+        INFO("SBC: Done copying full codec config");
+        return ((void *)(&sbc_codec));
+    } else if (codec_cfg[CODEC_OFFSET] == CODEC_TYPE_AAC)
+    {
+        uint16_t aac_samp_freq = 0;
+        uint32_t aac_bit_rate = 0;
+        memset(&aac_codec,0,sizeof(audio_aac_encoder_config));
+        p_cfg++;//skip dev idx
+        len = *p_cfg++;
+        p_cfg++;//skip media type
+        len--;
+        p_cfg++;//skip codec type
+        len--;
+        byte = *p_cfg++;
+        len--;
+        switch (byte & A2D_AAC_IE_OBJ_TYPE_MSK)
+        {
+            case A2D_AAC_IE_OBJ_TYPE_MPEG_2_AAC_LC:
+                aac_codec.enc_mode = AUDIO_FORMAT_AAC_SUB_LC;
+                break;
+            case A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_LC:
+                aac_codec.enc_mode = AUDIO_FORMAT_AAC_SUB_LC;
+                break;
+            case A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_LTP:
+                aac_codec.enc_mode = AUDIO_FORMAT_AAC_SUB_LTP;
+                break;
+            case A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_SCA:
+                aac_codec.enc_mode = AUDIO_FORMAT_AAC_SUB_SCALABLE;
+                break;
+            default:
+                ERROR("Unknown encoder mode");
+        }
+        //USE 0 (AAC_LC) as hardcoded value till Audio
+        //define constants
+        aac_codec.enc_mode = 0;
+        //USE LOAS(1) or LATM(4) hardcoded values till
+        //Audio define proper constants
+        aac_codec.format_flag = 4;
+        byte = *p_cfg++;
+        len--;
+        aac_samp_freq = byte << 8; //1st byte of sample_freq
+        byte = *p_cfg++;
+        len--;
+        aac_samp_freq |= byte & 0x00F0; //1st nibble of second byte of samp_freq
+
+        switch (aac_samp_freq) {
+            case 0x8000: aac_codec.sampling_rate = 8000; break;
+            case 0x4000: aac_codec.sampling_rate = 11025; break;
+            case 0x2000: aac_codec.sampling_rate = 12000; break;
+            case 0x1000: aac_codec.sampling_rate = 16000; break;
+            case 0x0800: aac_codec.sampling_rate = 22050; break;
+            case 0x0400: aac_codec.sampling_rate = 24000; break;
+            case 0x0200: aac_codec.sampling_rate = 32000; break;
+            case 0x0100: aac_codec.sampling_rate = 44100; break;
+            case 0x0080: aac_codec.sampling_rate = 48000; break;
+            case 0x0040: aac_codec.sampling_rate = 64000; break;
+            case 0x0020: aac_codec.sampling_rate = 88200; break;
+            case 0x0010: aac_codec.sampling_rate = 96000; break;
+            default:
+                ERROR("Invalid sample_freq: %x", aac_samp_freq);
+        }
+
+        switch (byte & A2D_AAC_IE_CHANNELS_MSK)
+        {
+            case A2D_AAC_IE_CHANNELS_1:
+                 aac_codec.channels = 1;
+                 break;
+            case A2D_AAC_IE_CHANNELS_2:
+                 aac_codec.channels = 2;
+                 break;
+            default:
+                 ERROR("Unknow channel mode");
+        }
+        byte = *p_cfg++; //Move to VBR byte
+        len--;
+        switch (byte & A2D_AAC_IE_VBR_MSK)
+        {
+            case A2D_AAC_IE_VBR:
+                break;
+            default:
+                ERROR("VBR not supported");
+        }
+        aac_bit_rate = 0x7F&byte;
+        //Move it 2nd byte of 32 bit word. leaving the VBR bit
+        aac_bit_rate = aac_bit_rate << 16;
+        byte = *p_cfg++; //Move to 2nd byteof bitrate
+        len--;
+
+        //Move it to 3rd byte of 32bit word
+        aac_bit_rate |= 0x0000FF00 & (((uint32_t)byte)<<8);
+        byte = *p_cfg++; //Move to 3rd byte of bitrate
+        len--;
+
+        aac_bit_rate |= 0x000000FF & (((uint32_t)byte));
+        aac_codec.bitrate = aac_bit_rate;
+
+        *codec_type = AUDIO_FORMAT_AAC;
+        INFO("AAC: Done copying full codec config");
+        return ((void *)(&aac_codec));
+    }
+    else if (codec_cfg[CODEC_OFFSET] == NON_A2DP_CODEC_TYPE)
+    {
+        if (codec_cfg[VENDOR_ID_OFFSET] == VENDOR_APTX &&
+            codec_cfg[CODEC_ID_OFFSET] == APTX_CODEC_ID)
+        {
+            INFO("AptX-classic codec");
+            *codec_type = AUDIO_FORMAT_APTX;
+        }
+        if (codec_cfg[VENDOR_ID_OFFSET] == VENDOR_APTX_HD &&
+            codec_cfg[CODEC_ID_OFFSET] == APTX_HD_CODEC_ID)
+        {
+            INFO("AptX-HD codec");
+            *codec_type = AUDIO_FORMAT_APTX_HD;
+        }
+        memset(&aptx_codec,0,sizeof(audio_aptx_encoder_config));
+        p_cfg++; //skip dev_idx
+        len = *p_cfg++;//LOSC
+        p_cfg++; // Skip media type
+        len--;
+        p_cfg++; //codec_type
+        len--;
+        p_cfg+=4;//skip vendor id
+        len -= 4;
+        p_cfg += 2; //skip codec id
+        len -= 2;
+        byte = *p_cfg++;
+        len--;
+        switch (byte & A2D_APTX_SAMP_FREQ_MASK)
+        {
+            case A2D_APTX_SAMP_FREQ_48:
+                 aptx_codec.sampling_rate = 48000;
+                 break;
+            case A2D_APTX_SAMP_FREQ_44:
+                 aptx_codec.sampling_rate = 44100;
+                 break;
+            default:
+                 ERROR("Unknown sampling rate");
+        }
+        switch (byte & A2D_APTX_CHAN_MASK)
+        {
+            case A2D_APTX_CHAN_STEREO:
+                 aptx_codec.channels = 2;
+                 break;
+            case A2D_APTX_CHAN_MONO:
+                 aptx_codec.channels = 1;
+                 break;
+            default:
+                 ERROR("Unknown channel mode");
+        }
+        if (*codec_type == AUDIO_FORMAT_APTX_HD) {
+            p_cfg += 4;
+            len -= 4;//ignore 4 bytes not used
+        }
+        if (len == 0)
+            INFO("Codec config copied");
+
+        p_cfg += 2; //skip mtu
+
+        aptx_codec.bitrate = *p_cfg++;
+        aptx_codec.bitrate |= (*p_cfg++ << 8);
+        aptx_codec.bitrate |= (*p_cfg++ << 16);
+        aptx_codec.bitrate |= (*p_cfg++ << 24);
+
+        INFO("APTx: Done copying full codec config");
+        return ((void *)&aptx_codec);
+    }
+    return NULL;
+}
+/*****************************************************************************
+**
+**   bluedroid stack adaptation
+**
+*****************************************************************************/
+
+static int skt_connect(char *path, size_t buffer_sz)
+{
+    int ret;
+    int skt_fd;
+    int len;
+
+    INFO("connect to %s (sz %zu)", path, buffer_sz);
+
+    skt_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+
+    if(osi_socket_local_client_connect(skt_fd, path,
+            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) < 0)
+    {
+        ERROR("failed to connect (%s)", strerror(errno));
+        close(skt_fd);
+        return -1;
+    }
+
+    len = buffer_sz;
+    ret = setsockopt(skt_fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, (int)sizeof(len));
+    if (ret < 0)
+        ERROR("setsockopt failed (%s)", strerror(errno));
+
+    ret = setsockopt(skt_fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, (int)sizeof(len));
+    if (ret < 0)
+        ERROR("setsockopt failed (%s)", strerror(errno));
+
+    /* Socket send/receive timeout value */
+    struct timeval tv;
+    tv.tv_sec = SOCK_SEND_TIMEOUT_MS / 1000;
+    tv.tv_usec = (SOCK_SEND_TIMEOUT_MS % 1000) * 1000;
+
+    ret = setsockopt(skt_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+    if (ret < 0)
+        ERROR("setsockopt failed (%s)", strerror(errno));
+
+    tv.tv_sec = SOCK_RECV_TIMEOUT_MS / 1000;
+    tv.tv_usec = (SOCK_RECV_TIMEOUT_MS % 1000) * 1000;
+
+    ret = setsockopt(skt_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+    if (ret < 0)
+        ERROR("setsockopt failed (%s)", strerror(errno));
+
+    INFO("connected to stack fd = %d", skt_fd);
+
+    return skt_fd;
+}
+
+static int skt_read(int fd, void *p, size_t len)
+{
+    ssize_t read;
+
+    FNLOG();
+
+    ts_log("skt_read recv", len, NULL);
+
+    OSI_NO_INTR(read = recv(fd, p, len, MSG_NOSIGNAL));
+    if (read == -1)
+        ERROR("read failed with errno=%d\n", errno);
+
+    return (int)read;
+}
+
+static int skt_write(int fd, const void *p, size_t len)
+{
+    ssize_t sent;
+
+    FNLOG();
+
+    ts_log("skt_write", len, NULL);
+
+    if (WRITE_POLL_MS == 0) {
+        // do not poll, use blocking send
+        OSI_NO_INTR(sent = send(fd, p, len, MSG_NOSIGNAL));
+        if (sent == -1)
+            ERROR("write failed with error(%s)", strerror(errno));
+
+        return (int)sent;
+    }
+
+    // use non-blocking send, poll
+    int ms_timeout = SOCK_SEND_TIMEOUT_MS;
+    size_t count = 0;
+    while (count < len) {
+        OSI_NO_INTR(sent = send(fd, p, len - count, MSG_NOSIGNAL | MSG_DONTWAIT));
+        if (sent == -1) {
+            if (errno != EAGAIN && errno != EWOULDBLOCK) {
+                ERROR("write failed with error(%s)", strerror(errno));
+                return -1;
+            }
+            if (ms_timeout >= WRITE_POLL_MS) {
+                usleep(WRITE_POLL_MS * 1000);
+                ms_timeout -= WRITE_POLL_MS;
+                continue;
+            }
+            WARN("write timeout exceeded, sent %zu bytes", count);
+            return -1;
+        }
+        count += sent;
+        p = (const uint8_t *)p + sent;
+    }
+    return (int)count;
+}
+
+static int skt_disconnect(int fd)
+{
+    INFO("fd %d", fd);
+
+    if (fd != AUDIO_SKT_DISCONNECTED)
+    {
+        shutdown(fd, SHUT_RDWR);
+        close(fd);
+    }
+    return 0;
+}
+
+
+
+/*****************************************************************************
+**
+**  AUDIO CONTROL PATH
+**
+*****************************************************************************/
+
+int a2dp_ctrl_receive(struct a2dp_stream_common *common, void* buffer, int length)
+{
+    ssize_t ret;
+    int i;
+
+    for (i = 0;; i++) {
+        OSI_NO_INTR(ret = recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL));
+        if (ret > 0) {
+            break;
+        }
+        if (ret == 0) {
+            ERROR("ack failed: peer closed");
+            break;
+        }
+        if (errno != EWOULDBLOCK && errno != EAGAIN) {
+            ERROR("ack failed: error(%s)", strerror(errno));
+            break;
+        }
+        if (i == (CTRL_CHAN_RETRY_COUNT + 1)) {
+            ERROR("ack failed: max retry count");
+            break;
+        }
+        INFO("ack failed (%s), retrying", strerror(errno));
+    }
+    if (ret <= 0) {
+        skt_disconnect(common->ctrl_fd);
+        common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
+    }
+    return ret;
+}
+
+int a2dp_command(struct a2dp_stream_common *common, char cmd)
+{
+    char ack;
+
+    INFO("A2DP COMMAND %s, fail count %d", dump_a2dp_ctrl_event(cmd),
+                                                open_ctrl_chnl_fail_count);
+
+    if ((common->ctrl_fd == AUDIO_SKT_DISCONNECTED)
+        && (open_ctrl_chnl_fail_count < 5)){
+        INFO("recovering from previous error");
+        a2dp_open_ctrl_path(common);
+        if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) {
+            ERROR("failure to open ctrl path");
+            return -1;
+        }
+    }
+    else if (open_ctrl_chnl_fail_count >= 5)
+    {
+        WARN("control channel open alreday failed 5 times, bailing out");
+        return -1;
+    }
+
+    /* send command */
+    ssize_t sent;
+    OSI_NO_INTR(sent = send(common->ctrl_fd, &cmd, 1, MSG_NOSIGNAL));
+    if (sent == -1)
+    {
+        ERROR("cmd failed (%s)", strerror(errno));
+        skt_disconnect(common->ctrl_fd);
+        common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
+        return -1;
+    }
+
+    /* wait for ack byte */
+    if (a2dp_ctrl_receive(common, &ack, 1) < 0) {
+        ERROR("A2DP COMMAND %s: no ACK", dump_a2dp_ctrl_event(cmd));
+        return -1;
+    }
+
+    INFO("A2DP COMMAND %s DONE STATUS %d", dump_a2dp_ctrl_event(cmd), ack);
+
+    if (ack == A2DP_CTRL_ACK_INCALL_FAILURE || ack == A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS)
+        return ack;
+    if (ack != A2DP_CTRL_ACK_SUCCESS) {
+        ERROR("A2DP COMMAND %s error %d", dump_a2dp_ctrl_event(cmd), ack);
+        return -1;
+    }
+    return 0;
+}
+
+int check_a2dp_ready(struct a2dp_stream_common *common)
+{
+    INFO("state %s", dump_a2dp_hal_state(common->state));
+    if (a2dp_command(common, A2DP_CTRL_CMD_CHECK_READY) < 0)
+    {
+        ERROR("check a2dp ready failed");
+        return -1;
+    }
+    return 0;
+}
+
+int a2dp_read_audio_config(struct a2dp_stream_common *common)
+{
+    uint32_t sample_rate;
+    uint8_t channel_count;
+
+    if (a2dp_command(common, A2DP_CTRL_GET_AUDIO_CONFIG) < 0)
+    {
+        ERROR("check a2dp ready failed");
+        return -1;
+    }
+
+    if (a2dp_ctrl_receive(common, &sample_rate, 4) < 0)
+        return -1;
+    if (a2dp_ctrl_receive(common, &channel_count, 1) < 0)
+        return -1;
+
+    common->cfg.channel_flags = (channel_count == 1 ? AUDIO_CHANNEL_IN_MONO : AUDIO_CHANNEL_IN_STEREO);
+    common->cfg.format = AUDIO_STREAM_DEFAULT_FORMAT;
+    common->cfg.rate = sample_rate;
+
+    INFO("got config %d %d", common->cfg.format, common->cfg.rate);
+
+    return 0;
+}
+
+int a2dp_read_codec_config(struct a2dp_stream_common *common,uint8_t idx)
+{
+    char cmd[2],ack;
+    int i,len = 0;
+    uint8_t *p_codec_cfg = common->codec_cfg;
+    cmd[0] = A2DP_CTRL_GET_CODEC_CONFIG;
+    cmd[1] = idx;
+    INFO("%s",__func__);
+    memset(p_codec_cfg,0,MAX_CODEC_CFG_SIZE);
+    INFO("%s",__func__);
+
+    if (send(common->ctrl_fd, cmd, 2,  MSG_NOSIGNAL) == -1)
+    {
+        ERROR("cmd failed (%s)", strerror(errno));
+        skt_disconnect(common->ctrl_fd);
+        common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
+        return -1;
+    }
+
+    if (a2dp_ctrl_receive(common, &ack, 1) < 0)
+        return -1;
+
+    if (ack != A2DP_CTRL_ACK_SUCCESS)
+    {
+        ERROR("%s: Failed to get ack",__func__);
+        return -1;
+    }
+    if ((a2dp_ctrl_receive(common, &len, 1) < 0) ||
+        (len <= 0) || (len > MAX_CODEC_CFG_SIZE))
+        return -1;
+    if (a2dp_ctrl_receive(common, p_codec_cfg, len) < 0)
+        return -1;
+
+    INFO("got codec config");
+    p_codec_cfg = common->codec_cfg;
+
+    for (i=0;i<len;i++)
+         INFO("code_config[%d] = %d ", i,*p_codec_cfg++);
+
+    return 0;
+}
+
+int a2dp_get_multicast_status(struct a2dp_stream_common *common, uint8_t *mcast_status,
+                               uint8_t *num_dev)
+{
+    INFO("%s",__func__);
+    if (a2dp_command(common,A2DP_CTRL_GET_MULTICAST_STATUS) < 0)
+    {
+        ERROR("check a2dp ready failed");
+        return -1;
+    }
+    INFO("a2dp_get_multicast_status acked fd = %d",common->ctrl_fd);
+    if (a2dp_ctrl_receive(common, mcast_status, 1) < 0)
+        return -1;
+    if (a2dp_ctrl_receive(common, num_dev, 1) < 0)
+        return -1;
+    INFO("%s: multicast status = %d, num_dev = %d",__func__,*mcast_status,*num_dev);
+    return 0;
+}
+
+void a2dp_open_ctrl_path(struct a2dp_stream_common *common)
+{
+    int i;
+
+    /* retry logic to catch any timing variations on control channel */
+    for (i = 0; i < CTRL_CHAN_RETRY_COUNT; i++)
+    {
+        /* connect control channel if not already connected */
+        if ((common->ctrl_fd = skt_connect(A2DP_CTRL_PATH, common->buffer_sz)) > 0)
+        {
+            /* success, now check if stack is ready */
+            if (check_a2dp_open_ready(common) == 0)
+            {
+                open_ctrl_chnl_fail_count = 0;
+                WARN("a2dp_open_ctrl_path : Fail count reset to 0");
+                return;
+            }
+            ERROR("a2dp_open_ctrl_path : No valid a2dp connection, abort");
+            usleep(100000);
+            skt_disconnect(common->ctrl_fd);
+            common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
+        }
+
+        /* ctrl channel not ready, wait a bit */
+        if (i < CTRL_CHAN_RETRY_COUNT - 1)
+        {
+            usleep(100000);
+        }
+    }
+    INFO("a2dp_open_ctrl_path : ctrl_fd: %d", common->ctrl_fd);
+    if (common->ctrl_fd <= 0)
+    {
+        open_ctrl_chnl_fail_count += 1;
+        WARN("a2dp_open_ctrl_path : Fail count raised to: %d",
+                                        open_ctrl_chnl_fail_count);
+    }
+}
+
+/*****************************************************************************
+**
+** AUDIO DATA PATH
+**
+*****************************************************************************/
+
+void a2dp_stream_common_init(struct a2dp_stream_common *common)
+{
+    pthread_mutexattr_t lock_attr;
+
+    FNLOG();
+
+    pthread_mutexattr_init(&lock_attr);
+    pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);
+    pthread_mutex_init(&common->lock, &lock_attr);
+
+    common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
+    common->audio_fd = AUDIO_SKT_DISCONNECTED;
+    common->state = AUDIO_A2DP_STATE_STOPPED;
+
+    /* manages max capacity of socket pipe */
+    common->buffer_sz = AUDIO_STREAM_OUTPUT_BUFFER_SZ;
+    bt_split_a2dp_enabled = false;
+}
+
+int start_audio_datapath(struct a2dp_stream_common *common)
+{
+    INFO("state %d", common->state);
+    int ret = 0;
+    #ifdef BT_AUDIO_SYSTRACE_LOG
+    char trace_buf[512];
+    #endif
+
+    INFO("state %s", dump_a2dp_hal_state(common->state));
+
+    int oldstate = common->state;
+    common->state = AUDIO_A2DP_STATE_STARTING;
+
+    int a2dp_status = a2dp_command(common, A2DP_CTRL_CMD_START);
+    #ifdef BT_AUDIO_SYSTRACE_LOG
+    snprintf(trace_buf, 32, "start_audio_data_path:");
+    if (PERF_SYSTRACE)
+    {
+        ATRACE_BEGIN(trace_buf);
+    }
+    #endif
+
+
+    #ifdef BT_AUDIO_SYSTRACE_LOG
+    if (PERF_SYSTRACE)
+    {
+        ATRACE_END();
+    }
+    #endif
+    if (a2dp_status < 0)
+    {
+        ERROR("%s Audiopath start failed (status %d)", __func__, a2dp_status);
+        ret = -1;
+        goto error;
+    }
+    else if (a2dp_status == A2DP_CTRL_ACK_INCALL_FAILURE)
+    {
+        ERROR("%s Audiopath start failed - in call, move to suspended", __func__);
+        ret = a2dp_status;
+        goto error;
+    }
+    else if (a2dp_status == A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS)
+    {
+        ERROR("%s Audiopath start failed - disconnection in progress", __func__);
+        ret = a2dp_status;
+        goto error;
+    }
+    if (!bt_split_a2dp_enabled)
+    {
+        /* connect socket if not yet connected */
+        if (common->audio_fd == AUDIO_SKT_DISCONNECTED)
+        {
+            common->audio_fd = skt_connect(A2DP_DATA_PATH, common->buffer_sz);
+            if (common->audio_fd < 0)
+            {
+                common->state = oldstate;
+                goto error;
+            }
+
+            common->state = AUDIO_A2DP_STATE_STARTED;
+        }
+    }
+    else
+    {
+        common->state = AUDIO_A2DP_STATE_STARTED;
+    }
+
+    return 0;
+error:
+    common->state = oldstate;
+    if (bt_split_a2dp_enabled)
+        return ret;
+    else
+        return -1;
+}
+
+int stop_audio_datapath(struct a2dp_stream_common *common)
+{
+    int oldstate = common->state;
+
+    INFO("state %s", dump_a2dp_hal_state(common->state));
+
+    if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED)
+         return -1;
+
+    /* prevent any stray output writes from autostarting the stream
+       while stopping audiopath */
+    common->state = AUDIO_A2DP_STATE_STOPPING;
+
+    if (a2dp_command(common, A2DP_CTRL_CMD_STOP) < 0)
+    {
+        ERROR("audiopath stop failed");
+        common->state = oldstate;
+        return -1;
+    }
+
+    common->state = AUDIO_A2DP_STATE_STOPPED;
+
+    if (!bt_split_a2dp_enabled)
+    {
+        /* disconnect audio path */
+        skt_disconnect(common->audio_fd);
+        common->audio_fd = AUDIO_SKT_DISCONNECTED;
+    }
+
+    return 0;
+}
+
+int suspend_audio_datapath(struct a2dp_stream_common *common, bool standby)
+{
+    INFO("state %s", dump_a2dp_hal_state(common->state));
+
+
+    if (common->state == AUDIO_A2DP_STATE_STOPPING)
+        return -1;
+
+    if (a2dp_command(common, A2DP_CTRL_CMD_SUSPEND) < 0)
+        return -1;
+
+    if (standby)
+        common->state = AUDIO_A2DP_STATE_STANDBY;
+    else
+        common->state = AUDIO_A2DP_STATE_SUSPENDED;
+
+    if (!bt_split_a2dp_enabled)
+    {
+        /* disconnect audio path */
+        skt_disconnect(common->audio_fd);
+
+        common->audio_fd = AUDIO_SKT_DISCONNECTED;
+    }
+
+    return 0;
+}
+
+int check_a2dp_stream_started(struct a2dp_stream_common *common)
+{
+   if (a2dp_command(common, A2DP_CTRL_CMD_CHECK_STREAM_STARTED) < 0)
+   {
+       INFO("Btif not in stream state");
+       return -1;
+   }
+   return 0;
+}
+static int check_a2dp_open_ready(struct a2dp_stream_common *common)
+{
+    if (a2dp_command(common, A2DP_CTRL_GET_CONNECTION_STATUS) < 0)
+    {
+        INFO("No active a2dp connection");
+        return -1;
+    }
+    return 0;
+}
+int audio_open_ctrl_path()
+{
+    INFO("%s",__func__);
+    a2dp_open_ctrl_path(&audio_stream);
+    if (audio_stream.ctrl_fd != AUDIO_SKT_DISCONNECTED)
+    {
+        INFO("control path opened successfull");
+        return 0;
+    }
+    else
+        INFO("control path open failed");
+    return -1;
+}
+
+int audio_start_stream()
+{
+    int i, status, j;
+    INFO("%s: state = %s",__func__,dump_a2dp_hal_state(audio_stream.state));
+
+    pthread_mutex_lock(&audio_stream.lock);
+    if (audio_stream.state == AUDIO_A2DP_STATE_SUSPENDED)
+    {
+        INFO("stream suspended");
+        pthread_mutex_unlock(&audio_stream.lock);
+        return -1;
+    }
+
+    if (audio_stream.state == AUDIO_A2DP_STATE_STARTED)
+    {
+        INFO("%s: stream alreday started", __func__);
+        pthread_mutex_unlock(&audio_stream.lock);
+        return 0;
+    }
+
+    /* Sanity check if the ctrl_fd is valid. If audio_stream_close is not called
+     * from audio hal previously when BT is turned off or device is disconnecte,
+     * and tries to start stream again.
+     */
+    if (check_a2dp_open_ready(&audio_stream) < 0)
+    {
+        if (audio_stream.ctrl_fd != AUDIO_SKT_DISCONNECTED)
+        {
+            ERROR("BTIF is not ready to start stream");
+            pthread_mutex_unlock(&audio_stream.lock);
+            return -1;
+        }
+        /* Try to start stream to recover from ctrl skt disconnect*/
+    }
+
+    for (j = 0; j <STREAM_START_MAX_RETRY_LOOPER; j++) {
+        for (i = 0; i < STREAM_START_MAX_RETRY_COUNT; i++)
+        {
+            status = start_audio_datapath(&audio_stream);
+            if (status == A2DP_CTRL_ACK_SUCCESS)
+            {
+                INFO("a2dp stream started successfully");
+                goto end;
+            }
+            else if (status == A2DP_CTRL_ACK_INCALL_FAILURE)
+            {
+                INFO("a2dp stream start failed: call in progress");
+                goto end;
+            }
+            else if (status == A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS)
+            {
+                INFO("a2dp stream start failed: disconnection in progress");
+                goto end;
+            }
+            if (audio_stream.ctrl_fd == AUDIO_SKT_DISCONNECTED)
+            {
+                INFO("control path is disconnected");
+                goto end;
+            }
+            INFO("%s: a2dp stream not started,wait 100mse & retry", __func__);
+            usleep(100000);
+        }
+        INFO("%s: Check if valid connection is still up or not", __func__);
+
+        // For every 1 sec check if a2dp is still up, to avoid
+        // blocking the audio thread forever if a2dp connection is closed
+        // for some reason
+        if (check_a2dp_open_ready (&audio_stream) < 0) {
+            ERROR("%s: No valid a2dp connection\n", __func__);
+            pthread_mutex_unlock(&audio_stream.lock);
+            return -1;
+        }
+    }
+end:
+    if (audio_stream.state != AUDIO_A2DP_STATE_STARTED)
+    {
+        ERROR("%s: Failed to start a2dp stream", __func__);
+        pthread_mutex_unlock(&audio_stream.lock);
+        return -1;
+    }
+    pthread_mutex_unlock(&audio_stream.lock);
+    return 0;
+}
+
+int audio_stream_open()
+{
+    INFO("%s",__func__);
+    a2dp_stream_common_init(&audio_stream);
+    open_ctrl_chnl_fail_count = 0;
+    a2dp_open_ctrl_path(&audio_stream);
+    bt_split_a2dp_enabled = true;
+    if (audio_stream.ctrl_fd != AUDIO_SKT_DISCONNECTED)
+    {
+        INFO("control path open successful");
+        /*Delay to ensure Headset is in proper state when START is initiated
+        from DUT immediately after the connection due to ongoing music playback. */
+        usleep(1000000);
+        a2dp_command(&audio_stream,A2DP_CTRL_CMD_OFFLOAD_SUPPORTED);
+        return 0;
+    }
+    else
+        INFO("control path open failed");
+
+    return -1;
+}
+
+int audio_stream_close()
+{
+    INFO("%s",__func__);
+
+    pthread_mutex_lock(&audio_stream.lock);
+    if (audio_stream.state == AUDIO_A2DP_STATE_STARTED ||
+        audio_stream.state == AUDIO_A2DP_STATE_STOPPING)
+    {
+        INFO("%s: Suspending audio stream",__func__);
+        suspend_audio_datapath(&audio_stream,true);
+    }
+
+    skt_disconnect(audio_stream.ctrl_fd);
+    audio_stream.ctrl_fd = AUDIO_SKT_DISCONNECTED;
+    pthread_mutex_unlock(&audio_stream.lock);
+    return 0;
+}
+int audio_stop_stream()
+{
+    INFO("%s state = %s",__func__,dump_a2dp_hal_state(audio_stream.state));
+    if (audio_stream.state != AUDIO_A2DP_STATE_SUSPENDED)
+    {
+        pthread_mutex_lock(&audio_stream.lock);
+        if (suspend_audio_datapath(&audio_stream, true) == 0)
+        {
+            INFO("audio stop stream successful");
+            pthread_mutex_unlock(&audio_stream.lock);
+            return 0;
+        }
+        audio_stream.state = AUDIO_A2DP_STATE_STOPPED;
+        pthread_mutex_unlock(&audio_stream.lock);
+        return -1;
+    }
+    return 0;
+}
+
+int audio_suspend_stream()
+{
+    INFO("%s state = %s",__func__,dump_a2dp_hal_state(audio_stream.state));
+    if (audio_stream.state != AUDIO_A2DP_STATE_SUSPENDED)
+    {
+        pthread_mutex_lock(&audio_stream.lock);
+        if (suspend_audio_datapath(&audio_stream, false) == 0)
+        {
+            INFO("audio suspend stream successful");
+            pthread_mutex_unlock(&audio_stream.lock);
+            return 0;
+        }
+        pthread_mutex_unlock(&audio_stream.lock);
+        return -1;
+    }
+    return 0;
+}
+
+void audio_handoff_triggered()
+{
+    INFO("%s state = %s",__func__,dump_a2dp_hal_state(audio_stream.state));
+    pthread_mutex_lock(&audio_stream.lock);
+    if (audio_stream.state != AUDIO_A2DP_STATE_STOPPED ||
+        audio_stream.state != AUDIO_A2DP_STATE_STOPPING)
+    {
+        audio_stream.state = AUDIO_A2DP_STATE_STOPPED;
+    }
+    pthread_mutex_unlock(&audio_stream.lock);
+}
+
+void clear_a2dpsuspend_flag()
+{
+    INFO("%s: state = %s",__func__,dump_a2dp_hal_state(audio_stream.state));
+    pthread_mutex_lock(&audio_stream.lock);
+    if (audio_stream.state == AUDIO_A2DP_STATE_SUSPENDED)
+        audio_stream.state = AUDIO_A2DP_STATE_STOPPED;
+    pthread_mutex_unlock(&audio_stream.lock);
+}
+
+void * audio_get_codec_config(uint8_t *multicast_status, uint8_t *num_dev,
+                              audio_format_t *codec_type)
+{
+    int i, status, j;
+    INFO("%s: state = %s",__func__,dump_a2dp_hal_state(audio_stream.state));
+
+    pthread_mutex_lock(&audio_stream.lock);
+    a2dp_get_multicast_status(&audio_stream, multicast_status,num_dev);
+
+    DEBUG("got multicast status = %d dev = %d",*multicast_status,*num_dev);
+
+    for (i = 0; i < STREAM_START_MAX_RETRY_COUNT; i++)
+    {
+        status = a2dp_read_codec_config(&audio_stream, 0);
+        if (status == A2DP_CTRL_ACK_SUCCESS)
+        {
+            pthread_mutex_unlock(&audio_stream.lock);
+            return (a2dp_codec_parser(&audio_stream.codec_cfg[0], codec_type));
+        }
+        INFO("%s: a2dp stream not configured,wait 100mse & retry", __func__);
+        usleep(100000);
+    }
+    pthread_mutex_unlock(&audio_stream.lock);
+    return NULL;
+}
+
+void* audio_get_next_codec_config(uint8_t idx, audio_format_t *codec_type)
+{
+    int i, status, j;
+    INFO("%s",__func__);
+    pthread_mutex_lock(&audio_stream.lock);
+    for (i = 0; i < STREAM_START_MAX_RETRY_COUNT; i++)
+    {
+        status = a2dp_read_codec_config(&audio_stream, 0);
+        if (status == A2DP_CTRL_ACK_SUCCESS)
+        {
+            pthread_mutex_unlock(&audio_stream.lock);
+            return (a2dp_codec_parser(&audio_stream.codec_cfg[0], codec_type));
+        }
+        INFO("%s: a2dp stream not configured,wait 100mse & retry", __func__);
+        usleep(100000);
+    }
+    pthread_mutex_unlock(&audio_stream.lock);
+    return NULL;
+}
+
+int audio_check_a2dp_ready()
+{
+    INFO("audio_check_a2dp_ready: state %s", dump_a2dp_hal_state(audio_stream.state));
+    pthread_mutex_lock(&audio_stream.lock);
+    if (audio_stream.state == AUDIO_A2DP_STATE_SUSPENDED)
+    {
+        INFO("stream not ready to start");
+        pthread_mutex_unlock(&audio_stream.lock);
+        return 0;
+    }
+    if (a2dp_command(&audio_stream, A2DP_CTRL_CMD_CHECK_READY) != 0)
+    {
+        INFO("audio_check_a2dp_ready: FAIL");
+        pthread_mutex_unlock(&audio_stream.lock);
+        return 0;
+    }
+    pthread_mutex_unlock(&audio_stream.lock);
+    return 1;
+}
+//Entry point for dynamic lib
+const bt_host_ipc_interface_t BTHOST_IPC_INTERFACE = {
+    sizeof(bt_host_ipc_interface_t),
+    a2dp_open_ctrl_path,
+    a2dp_stream_common_init,
+    start_audio_datapath,
+    suspend_audio_datapath,
+    stop_audio_datapath,
+    check_a2dp_stream_started,
+    check_a2dp_ready,
+    a2dp_read_audio_config,
+    skt_read,
+    skt_write,
+    skt_disconnect,
+    a2dp_command,
+    audio_stream_open,
+    audio_stream_close,
+    audio_start_stream,
+    audio_stop_stream,
+    audio_suspend_stream,
+    audio_get_codec_config,
+    audio_handoff_triggered,
+    clear_a2dpsuspend_flag,
+    audio_get_next_codec_config,
+    audio_check_a2dp_ready
+};
diff --git a/audio_a2dp_hw/bthost_ipc.h b/audio_a2dp_hw/bthost_ipc.h
new file mode 100644
index 0000000..d0a561a
--- /dev/null
+++ b/audio_a2dp_hw/bthost_ipc.h
@@ -0,0 +1,171 @@
+/******************************************************************************
+ *  Copyright (C) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a Contribution
+ *****************************************************************************/
+/*****************************************************************************
+ *  Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/*****************************************************************************
+ *
+ *  Filename:      audio_a2dp_hw.h
+ *
+ *  Description:
+ *
+ *****************************************************************************/
+#ifndef BT_HOST_IPC_H
+#define BT_HOST_IPC_H
+#include "audio_a2dp_hw.h"
+#include <system/audio.h>
+/*****************************************************************************
+**  Constants & Macros
+******************************************************************************/
+
+#define BT_AUDIO_HARDWARE_INTERFACE "libbthost"
+#define A2DP_CTRL_PATH "/data/misc/bluedroid/.a2dp_ctrl"
+#define A2DP_DATA_PATH "/data/misc/bluedroid/.a2dp_data"
+
+typedef enum {
+    A2DP_CTRL_GET_CODEC_CONFIG = 15,
+    A2DP_CTRL_GET_MULTICAST_STATUS,
+    A2DP_CTRL_GET_CONNECTION_STATUS,
+} tA2DP_CTRL_EXT_CMD;
+
+/*
+codec specific definitions
+*/
+#define CODEC_TYPE_SBC 0x00
+#define CODEC_TYPE_AAC 0x02
+#define NON_A2DP_CODEC_TYPE 0xFF
+#define CODEC_OFFSET 3
+#define VENDOR_ID_OFFSET 4
+#define CODEC_ID_OFFSET (VENDOR_ID_OFFSET + 4)
+#define CODEC_TYPE_PCM 0x05
+
+#ifndef VENDOR_APTX
+#define VENDOR_APTX 0x4F
+#endif
+#ifndef VENDOR_APTX_HD
+#define VENDOR_APTX_HD 0xD7
+#endif
+#ifndef VENDOR_APTX_LL
+#define VENDOR_APTX_LL 0x0A
+#endif
+#ifndef APTX_CODEC_ID
+#define APTX_CODEC_ID 0x01
+#endif
+#ifndef APTX_HD_CODEC_ID
+#define APTX_HD_CODEC_ID 0x24
+#endif
+
+#define A2D_SBC_FREQ_MASK 0xF0
+#define A2D_SBC_CHN_MASK  0x0F
+#define A2D_SBC_BLK_MASK  0xF0
+#define A2D_SBC_SUBBAND_MASK 0x0C
+#define A2D_SBC_ALLOC_MASK 0x03
+#define A2D_SBC_SAMP_FREQ_16     0x80    /* b7:16  kHz */
+#define A2D_SBC_SAMP_FREQ_32     0x40    /* b6:32  kHz */
+#define A2D_SBC_SAMP_FREQ_44     0x20    /* b5:44.1kHz */
+#define A2D_SBC_SAMP_FREQ_48     0x10    /* b4:48  kHz */
+#define A2D_SBC_CH_MD_MONO       0x08    /* b3: mono */
+#define A2D_SBC_CH_MD_DUAL       0x04    /* b2: dual */
+#define A2D_SBC_CH_MD_STEREO     0x02    /* b1: stereo */
+#define A2D_SBC_CH_MD_JOINT      0x01    /* b0: joint stereo */
+#define A2D_SBC_BLOCKS_4         0x80    /* 4 blocks */
+#define A2D_SBC_BLOCKS_8         0x40    /* 8 blocks */
+#define A2D_SBC_BLOCKS_12        0x20    /* 12blocks */
+#define A2D_SBC_BLOCKS_16        0x10    /* 16blocks */
+#define A2D_SBC_SUBBAND_4        0x08    /* b3: 4 */
+#define A2D_SBC_SUBBAND_8        0x04    /* b2: 8 */
+#define A2D_SBC_ALLOC_MD_S       0x02    /* b1: SNR */
+#define A2D_SBC_ALLOC_MD_L       0x01    /* b0: loundess */
+
+/* APTX bitmask helper */
+#define A2D_APTX_SAMP_FREQ_MASK  0xF0
+#define A2D_APTX_SAMP_FREQ_48    0x10
+#define A2D_APTX_SAMP_FREQ_44    0x20
+#define A2D_APTX_CHAN_MASK       0x0F
+#define A2D_APTX_CHAN_STEREO     0x02
+#define A2D_APTX_CHAN_MONO       0x01
+
+
+#define A2D_AAC_IE_OBJ_TYPE_MSK                0xF0    /* b7-b4 Object Type */
+#define A2D_AAC_IE_OBJ_TYPE_MPEG_2_AAC_LC      0x80    /* b7:MPEG-2 AAC LC */
+#define A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_LC      0x40    /* b7:MPEG-4 AAC LC */
+#define A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_LTP     0x20    /* b7:MPEG-4 AAC LTP */
+#define A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_SCA     0x10    /* b7:MPEG-4 AAC SCALABLE */
+
+#define A2D_AAC_IE_CHANNELS_MSK                0x0C
+#define A2D_AAC_IE_CHANNELS_1                  0x08    /* Channel 1 */
+#define A2D_AAC_IE_CHANNELS_2                  0x04    /* Channel 2 */
+
+#define A2D_AAC_IE_VBR_MSK                     0x80
+#define A2D_AAC_IE_VBR                         0x80    /* supported */
+
+typedef struct {
+    uint8_t  codec_type;
+    uint8_t  dev_idx;
+    uint16_t sampling_rate; /*44.1khz,48khz*/
+    uint8_t  chn;           /*0(Mono),1(Dual),2(Stereo),3(JS)*/
+    uint8_t  blk_len;       /*4,8,12,16 */
+    uint8_t  subband;       /*4,8*/
+    uint8_t  alloc;         /*0(Loudness),1(SNR)*/
+    uint8_t  min_bitpool;   /* 2 */
+    uint8_t  max_bitpool;   /*53(44.1khz),51 (48khz) */
+    uint16_t mtu;
+    uint32_t bitrate;
+}tA2DP_SBC_CODEC;
+
+typedef struct {
+    uint8_t  codec_type;
+    uint8_t  dev_idx;
+    uint32_t vendor_id;
+    uint16_t codec_id;
+    uint16_t sampling_rate;
+    uint8_t  chnl;
+    uint8_t  cp;
+    uint16_t mtu;
+    uint32_t bitrate;
+}tA2DP_APTX_CODEC;
+
+typedef struct {
+    /** Set to sizeof(bt_host_ipc_interface_t) */
+    size_t          size;
+    void (*a2dp_open_ctrl_path)(struct a2dp_stream_common *common);
+    void (*a2dp_stream_common_init)(struct a2dp_stream_common *common);
+    int (*start_audio_datapath)(struct a2dp_stream_common *common);
+    int (*suspend_audio_datapath)(struct a2dp_stream_common *common, bool standby);
+    int (*stop_audio_datapath)(struct a2dp_stream_common *common);
+    int (*check_a2dp_stream_started)(struct a2dp_stream_common *common);
+    int (*check_a2dp_ready)(struct a2dp_stream_common *common);
+    int (*a2dp_read_audio_config)(struct a2dp_stream_common *common);
+    int (*skt_read)(int fd,void *buf, size_t bytes);
+    int (*skt_write)(int fd,const void *buf, size_t bytes);
+    int (*skt_disconnect)(int fd);
+    int (*a2dp_command)(struct a2dp_stream_common *common,char cmd);
+    int (*audio_stream_open)(void);
+    int (*audio_stream_close)(void);
+    int (*audio_start_stream)(void);
+    int (*audio_stop_stream)(void);
+    int (*audio_suspend_stream)(void);
+    void* (*audio_get_codec_config)(uint8_t *mcast, uint8_t *num_dev, audio_format_t *codec_type);
+    void (*audio_handoff_triggered)(void);
+    void (*clear_a2dpsuspend_flag)(void);
+    void*(*audio_get_next_codec_config)(uint8_t idx, audio_format_t *codec_type);
+    int (*audio_check_a2dp_ready)(void);
+} bt_host_ipc_interface_t;
+#endif
diff --git a/bta/Android.mk b/bta/Android.mk
index 6dc6a3e..7512d64 100644
--- a/bta/Android.mk
+++ b/bta/Android.mk
@@ -57,6 +57,7 @@
     ./av/bta_av_cfg.c \
     ./av/bta_av_ssm.c \
     ./av/bta_av_sbc.c \
+    ./av/bta_av_aac.c \
     ./ar/bta_ar.c \
     ./hl/bta_hl_act.c \
     ./hl/bta_hl_api.c \
@@ -97,6 +98,14 @@
                    $(LOCAL_PATH)/../utils/include \
                    $(bluetooth_C_INCLUDES)
 
+ifneq ($(TARGET_SUPPORTS_WEARABLES),true)
+LOCAL_C_INCLUDES+= . \
+                   vendor/qcom/opensource/bluetooth/system_bt_ext
+else
+LOCAL_C_INCLUDES+= . \
+                   device/qcom/msm8909w/opensource/bluetooth/system_bt_ext
+endif
+
 LOCAL_CFLAGS += $(bluetooth_CFLAGS) -DBUILDCFG
 LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS)
 LOCAL_CPPFLAGS += $(bluetooth_CPPFLAGS)
diff --git a/bta/ag/bta_ag_act.c b/bta/ag/bta_ag_act.c
index e93acb2..3cacaf3 100644
--- a/bta/ag/bta_ag_act.c
+++ b/bta/ag/bta_ag_act.c
@@ -32,7 +32,9 @@
 #include <string.h>
 #include "bta_dm_int.h"
 #include "l2c_api.h"
-
+#include <cutils/properties.h>
+#include <hardware/bluetooth.h>
+#include "device/include/interop.h"
 /*****************************************************************************
 **  Constants
 *****************************************************************************/
@@ -105,6 +107,12 @@
         bdcpy(open.bd_addr, p_scb->peer_addr);
     }
 
+    // if failure, dump logs
+    if (status != BTA_AG_SUCCESS) {
+        APPL_TRACE_WARNING("%s: there is failure in SDP/RFCOMM connection", __func__);
+        GENERATE_VND_LOGS();
+    }
+
     (*bta_ag_cb.p_cback)(BTA_AG_OPEN_EVT, (tBTA_AG *) &open);
 }
 
@@ -200,6 +208,7 @@
 void bta_ag_start_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
 {
     BD_ADDR pending_bd_addr;
+    tBTA_AG_RFC     *p_buf;
 
     /* store parameters */
     if (p_data)
@@ -212,6 +221,26 @@
     /* Check if RFCOMM has any incoming connection to avoid collision. */
     if (PORT_IsOpening (pending_bd_addr))
     {
+        char value[PROPERTY_VALUE_MAX];
+        if (property_get("persist.bt.max.hs.connections", value, "") &&
+                     !strcmp(value, "2") )
+        {
+            // Abort the outgoing connection if incoming connection is from the same device
+            if (bdcmp (pending_bd_addr, p_scb->peer_addr) == 0)
+            {
+                APPL_TRACE_WARNING("%s: p_scb %x, abort outgoing conn, there is"\
+                    " an incoming conn from dev %x:%x:%x:%x:%x:%x", __func__,
+                    p_scb, p_scb->peer_addr[0], p_scb->peer_addr[1],
+                    p_scb->peer_addr[2], p_scb->peer_addr[3], p_scb->peer_addr[4],
+                    p_scb->peer_addr[5]);
+                // send ourselves close event for clean up
+                p_buf = (tBTA_AG_RFC *) osi_malloc(sizeof(tBTA_AG_RFC));
+                p_buf->hdr.event = BTA_AG_RFC_CLOSE_EVT;
+                p_buf->hdr.layer_specific = bta_ag_scb_to_idx(p_scb);
+                bta_sys_sendmsg(p_buf);
+                return;
+            }
+        }
         /* Let the incoming connection goes through.                        */
         /* Issue collision for this scb for now.                            */
         /* We will decide what to do when we find incoming connetion later. */
@@ -430,11 +459,9 @@
     p_scb->post_sco = BTA_AG_POST_SCO_NONE;
     p_scb->svc_conn = FALSE;
     p_scb->hsp_version = HSP_VERSION_1_2;
+    p_scb->slc_pend_open = FALSE;
     bta_ag_at_reinit(&p_scb->at_cb);
 
-    memset(&(p_scb->peer_hf_indicators), 0, sizeof(p_scb->peer_hf_indicators));
-    memset(&(p_scb->local_hf_indicators), 0, sizeof(p_scb->local_hf_indicators));
-
     /* stop timers */
     alarm_cancel(p_scb->ring_timer);
 #if (BTM_WBS_INCLUDED == TRUE)
@@ -506,6 +533,9 @@
 *******************************************************************************/
 void bta_ag_rfc_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
 {
+    int ag_conn_timeout = p_bta_ag_cfg->conn_tout;
+    bt_bdaddr_t remote_bdaddr;
+    bdcpy(remote_bdaddr.address, p_scb->peer_addr);
     /* initialize AT feature variables */
     p_scb->clip_enabled = FALSE;
     p_scb->ccwa_enabled = FALSE;
@@ -528,9 +558,15 @@
 
     bta_ag_cback_open(p_scb, NULL, BTA_AG_SUCCESS);
 
+    if (interop_match_addr(INTEROP_INCREASE_AG_CONN_TIMEOUT,
+                            (const bt_bdaddr_t*)&remote_bdaddr)) {
+       /* use higher value for ag conn timeout */
+       ag_conn_timeout = 20000;
+    }
+    APPL_TRACE_DEBUG ("bta_ag_rfc_open: ag_conn_timeout: %d", ag_conn_timeout);
     if (p_scb->conn_service == BTA_AG_HFP) {
         /* if hfp start timer for service level conn */
-        bta_sys_start_timer(p_scb->ring_timer, p_bta_ag_cfg->conn_tout,
+        bta_sys_start_timer(p_scb->ring_timer, ag_conn_timeout,
                             BTA_AG_SVC_TIMEOUT_EVT, bta_ag_scb_to_idx(p_scb));
     } else {
         /* else service level conn is open */
@@ -555,11 +591,12 @@
     tBTA_AG_SCB     *ag_scb, *other_scb;
     BD_ADDR         dev_addr;
     int             status;
+    tBTA_AG_RFC     *p_buf;
 
     /* set role */
     p_scb->role = BTA_AG_ACP;
 
-    APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open: serv_handle0 = %d serv_handle1 = %d",
+    APPL_TRACE_IMP ("bta_ag_rfc_acp_open: serv_handle0 = %d serv_handle1 = %d",
                        p_scb->serv_handle[0], p_scb->serv_handle[1]);
 
     /* get bd addr of peer */
@@ -577,8 +614,30 @@
 
             if (bdcmp (dev_addr, ag_scb->peer_addr) == 0)
             {
-                /* If incoming and outgoing device are same, nothing more to do.            */
-                /* Outgoing conn will be aborted because we have successful incoming conn.  */
+                char value[PROPERTY_VALUE_MAX];
+                /* Read the property if multi hf is enabled */
+                if (property_get("persist.bt.max.hs.connections", value, "") &&
+                     !strcmp(value, "2") )
+                {
+                    /* If incoming and outgoing device are same, nothing more to do.            */
+                    /* Outgoing conn will be aborted because we have successful incoming conn.  */
+                    APPL_TRACE_WARNING("%s: p_scb %x, abort outgoing conn,"\
+                      "there is an incoming conn from dev %x:%x:%x:%x:%x:%x",
+                      __func__, ag_scb, dev_addr[0], dev_addr[1], dev_addr[2],
+                      dev_addr[3], dev_addr[4], dev_addr[5]);
+                    if (ag_scb->conn_handle)
+                    {
+                        RFCOMM_RemoveConnection(ag_scb->conn_handle);
+                    }
+
+                    // send ourselves close event for clean up
+                    // move back to OPENING state from INIT state so that clean up is done
+                    ag_scb->state = 1;
+                    p_buf = (tBTA_AG_RFC *) osi_malloc(sizeof(tBTA_AG_RFC));
+                    p_buf->hdr.event = BTA_AG_RFC_CLOSE_EVT;
+                    p_buf->hdr.layer_specific = bta_ag_scb_to_idx(ag_scb);
+                    bta_sys_sendmsg(p_buf);
+                }
             }
             else
             {
@@ -614,7 +673,7 @@
         }
     }
 
-    APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open: conn_service = %d conn_handle = %d",
+    APPL_TRACE_IMP ("bta_ag_rfc_acp_open: conn_service = %d conn_handle = %d",
                        p_scb->conn_service, p_scb->conn_handle);
 
     /* close any unopened server */
@@ -670,7 +729,7 @@
         bta_ag_at_parse(&p_scb->at_cb, buf, len);
         if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) && bta_ag_sco_is_open(p_scb))
         {
-            APPL_TRACE_DEBUG ("%s change link policy for SCO", __func__);
+            APPL_TRACE_IMP("bta_ag_rfc_data, change link policy for SCO");
             bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
         } else {
             bta_sys_idle(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
@@ -866,7 +925,7 @@
     PORT_WriteData(p_scb->conn_handle, p_data_area, strlen(p_data_area), &len);
     if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) && bta_ag_sco_is_open(p_scb))
     {
-        APPL_TRACE_DEBUG ("bta_ag_rfc_data, change link policy for SCO");
+        APPL_TRACE_IMP("bta_ag_rfc_data, change link policy for SCO");
         bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
     }
     else
@@ -912,6 +971,9 @@
 #if (BTM_WBS_INCLUDED == TRUE )
     tBTA_AG_PEER_CODEC codec_type = p_data->api_setcodec.codec;
     tBTA_AG_VAL        val;
+    val.hdr.handle = bta_ag_scb_to_idx(p_scb);
+    val.hdr.app_id = p_scb->app_id;
+    bdcpy(val.bd_addr, p_scb->peer_addr);
 
     /* Check if the requested codec type is valid */
     if((codec_type != BTA_AG_CODEC_NONE) &&
diff --git a/bta/ag/bta_ag_at.c b/bta/ag/bta_ag_at.c
index 952f1f8..6b4b657 100644
--- a/bta/ag/bta_ag_at.c
+++ b/bta/ag/bta_ag_at.c
@@ -156,14 +156,14 @@
                 {
 
                     (*p_cb->p_cmd_cback)(p_cb->p_user,
-                                         p_cb->p_at_tbl[idx].command_id,
+                                         idx,
                                          arg_type, p_arg, p_end, int_arg);
                 }
             }
             else
             {
                 (*p_cb->p_cmd_cback)(p_cb->p_user,
-                                     p_cb->p_at_tbl[idx].command_id,
+                                     idx,
                                      arg_type, p_arg, p_end, int_arg);
             }
         }
diff --git a/bta/ag/bta_ag_at.h b/bta/ag/bta_ag_at.h
index b2dae6e..c0ba7fb 100644
--- a/bta/ag/bta_ag_at.h
+++ b/bta/ag/bta_ag_at.h
@@ -47,7 +47,6 @@
 typedef struct
 {
     const char  *p_cmd;         /* AT command string */
-    size_t      command_id;     /* passed to the callback on p_cmd match */
     UINT8       arg_type;       /* allowable argument type syntax */
     UINT8       fmt;            /* whether arg is int or string */
     UINT8       min;            /* minimum value for int arg */
@@ -55,7 +54,7 @@
 } tBTA_AG_AT_CMD;
 
 /* callback function executed when command is parsed */
-typedef void (tBTA_AG_AT_CMD_CBACK)(void *p_user, UINT16 command_id, UINT8 arg_type,
+typedef void (tBTA_AG_AT_CMD_CBACK)(void *p_user, UINT16 cmd, UINT8 arg_type,
                                     char *p_arg, char *p_end, INT16 int_arg);
 
 /* callback function executed to send "ERROR" result code */
diff --git a/bta/ag/bta_ag_cfg.c b/bta/ag/bta_ag_cfg.c
index e5893e1..cfe298a 100644
--- a/bta/ag/bta_ag_cfg.c
+++ b/bta/ag/bta_ag_cfg.c
@@ -52,24 +52,9 @@
                                                                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
 #endif
 
-#ifndef BTA_AG_BIND_INFO
-#define BTA_AG_BIND_INFO "(1)"
-#endif
-
-const tBTA_AG_HF_IND bta_ag_local_hf_ind_cfg[] =
-{
-    /* The first row contains the number of indicators. Need to be updated accordingly */
-    {BTA_AG_NUM_LOCAL_HF_IND,   0,  0,  0,  0},
-
-    {1,    1,   1,   0,    1},     /* Enhanced Driver Status, supported, enabled, range 0 ~ 1 */
-    {2,    1,   1,   0,    100}    /* Battery Level Status, supported, enabled, range 0 ~ 100 */
-};
-
 const tBTA_AG_CFG bta_ag_cfg =
 {
     BTA_AG_CIND_INFO,
-    BTA_AG_BIND_INFO,
-    BTA_AG_NUM_LOCAL_HF_IND,
     BTA_AG_CONN_TIMEOUT,
     BTA_AG_SCO_PKT_TYPES,
     BTA_AG_CHLD_VAL_ECC,
diff --git a/bta/ag/bta_ag_cmd.c b/bta/ag/bta_ag_cmd.c
index 7a882ec..c381011 100644
--- a/bta/ag/bta_ag_cmd.c
+++ b/bta/ag/bta_ag_cmd.c
@@ -16,11 +16,15 @@
  *
  ******************************************************************************/
 
-#define LOG_TAG "bta_ag_cmd"
-
+/******************************************************************************
+ *
+ *  This file contains functions for processing AT commands and results.
+ *
+ ******************************************************************************/
 #include <ctype.h>
 #include <stdio.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include "bt_target.h"
 #include "bt_types.h"
@@ -31,10 +35,11 @@
 #include "bta_sys.h"
 #include "log/log.h"
 #include "bt_common.h"
-#include "osi/include/log.h"
 #include "port_api.h"
 #include "utl.h"
-
+#include <cutils/properties.h>
+#include "device/include/interop.h"
+#include "btif/include/btif_storage.h"
 
 /*****************************************************************************
 **  Constants
@@ -54,73 +59,116 @@
 #define BTA_AG_CLIP_TYPE_DEFAULT    129
 #define BTA_AG_CLIP_TYPE_VOIP       255
 
-#define COLON_IDX_4_VGSVGM    4
+#if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
+#define BTA_AG_AT_MULTI_LEN            2
+#define AT_SET_RES_CB(res_cb, c, p, i) {res_cb.code = c; res_cb.p_arg = p; res_cb.int_arg = i;}
 
-/* Local events which will not trigger a higher layer callback */
+/* type for AT result code block */
+typedef struct
+{
+    UINT8 code;
+    char *p_arg;
+    INT16 int_arg;
+} tBTA_AG_RESULT_CB;
+
+/* type for multiple AT result codes block */
+typedef struct
+{
+    UINT8 num_result;
+    tBTA_AG_RESULT_CB res_cb[BTA_AG_AT_MULTI_LEN];
+} tBTA_AG_MULTI_RESULT_CB;
+#endif
+
+/* enumeration of HSP AT commands matches HSP command interpreter table */
 enum
 {
-    BTA_AG_LOCAL_EVT_FIRST = 0x100,
-    BTA_AG_LOCAL_EVT_CCWA,
-    BTA_AG_LOCAL_EVT_CLIP,
-    BTA_AG_LOCAL_EVT_CMER,
-    BTA_AG_LOCAL_EVT_BRSF,
-    BTA_AG_LOCAL_EVT_CMEE,
-    BTA_AG_LOCAL_EVT_BIA,
-    BTA_AG_LOCAL_EVT_BCC,
+    BTA_AG_HS_CMD_CKPD,
+    BTA_AG_HS_CMD_VGS,
+    BTA_AG_HS_CMD_VGM
+};
+
+/* enumeration of HFP AT commands matches HFP command interpreter table */
+enum
+{
+    BTA_AG_HF_CMD_A,
+    BTA_AG_HF_CMD_D,
+    BTA_AG_HF_CMD_VGS,
+    BTA_AG_HF_CMD_VGM,
+    BTA_AG_HF_CMD_CCWA,
+    BTA_AG_HF_CMD_CHLD,
+    BTA_AG_HF_CMD_CHUP,
+    BTA_AG_HF_CMD_CIND,
+    BTA_AG_HF_CMD_CLIP,
+    BTA_AG_HF_CMD_CMER,
+    BTA_AG_HF_CMD_VTS,
+    BTA_AG_HF_CMD_BINP,
+    BTA_AG_HF_CMD_BLDN,
+    BTA_AG_HF_CMD_BVRA,
+    BTA_AG_HF_CMD_BRSF,
+    BTA_AG_HF_CMD_NREC,
+    BTA_AG_HF_CMD_CNUM,
+    BTA_AG_HF_CMD_BTRH,
+    BTA_AG_HF_CMD_CLCC,
+    BTA_AG_HF_CMD_COPS,
+    BTA_AG_HF_CMD_CMEE,
+    BTA_AG_HF_CMD_BIA,
+    BTA_AG_HF_CMD_CBC,
+    BTA_AG_HF_CMD_BCC,
+    BTA_AG_HF_CMD_BCS,
+    BTA_AG_HF_CMD_BAC,
+    BTA_AG_HF_CMD_BIND,
+    BTA_AG_HF_CMD_BIEV
 };
 
 /* AT command interpreter table for HSP */
 const tBTA_AG_AT_CMD bta_ag_hsp_cmd[] =
 {
-    {"+CKPD", BTA_AG_AT_CKPD_EVT, BTA_AG_AT_SET,   BTA_AG_AT_INT, 200, 200},
-    {"+VGS",  BTA_AG_SPK_EVT,     BTA_AG_AT_SET,   BTA_AG_AT_INT,   0,  15},
-    {"+VGM",  BTA_AG_MIC_EVT,     BTA_AG_AT_SET,   BTA_AG_AT_INT,   0,  15},
-    /* End-of-table marker used to stop lookup iteration */
-    {"", 0, 0, 0, 0, 0}
+    {"+CKPD",   BTA_AG_AT_SET,                      BTA_AG_AT_INT, 200, 200},
+    {"+VGS",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,  15},
+    {"+VGM",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,  15},
+    {"",        BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0}
 };
 
 /* AT command interpreter table for HFP */
 const tBTA_AG_AT_CMD bta_ag_hfp_cmd[] =
 {
-    {"A",     BTA_AG_AT_A_EVT,    BTA_AG_AT_NONE, BTA_AG_AT_STR,   0,   0},
-    {"D",     BTA_AG_AT_D_EVT,    BTA_AG_AT_NONE | BTA_AG_AT_FREE, BTA_AG_AT_STR, 0, 0},
-    {"+VGS",  BTA_AG_SPK_EVT,     BTA_AG_AT_SET,  BTA_AG_AT_INT,   0,  15},
-    {"+VGM",  BTA_AG_MIC_EVT,     BTA_AG_AT_SET,  BTA_AG_AT_INT,   0,  15},
-    {"+CCWA", BTA_AG_LOCAL_EVT_CCWA, BTA_AG_AT_SET,  BTA_AG_AT_INT,   0,   1},
+    {"A",       BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
+    {"D",       (BTA_AG_AT_NONE | BTA_AG_AT_FREE),  BTA_AG_AT_STR,   0,   0},
+    {"+VGS",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,  15},
+    {"+VGM",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,  15},
+    {"+CCWA",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   1},
     /* Consider CHLD as str to take care of indexes for ECC */
-    {"+CHLD", BTA_AG_AT_CHLD_EVT, BTA_AG_AT_SET | BTA_AG_AT_TEST, BTA_AG_AT_STR, 0, 4},
-    {"+CHUP", BTA_AG_AT_CHUP_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR,   0,   0},
-    {"+CIND", BTA_AG_AT_CIND_EVT, BTA_AG_AT_READ | BTA_AG_AT_TEST, BTA_AG_AT_STR, 0, 0},
-    {"+CLIP", BTA_AG_LOCAL_EVT_CLIP, BTA_AG_AT_SET,  BTA_AG_AT_INT,   0,   1},
-    {"+CMER", BTA_AG_LOCAL_EVT_CMER, BTA_AG_AT_SET,  BTA_AG_AT_STR,   0,   0},
-    {"+VTS",  BTA_AG_AT_VTS_EVT,  BTA_AG_AT_SET,  BTA_AG_AT_STR,   0,   0},
-    {"+BINP", BTA_AG_AT_BINP_EVT, BTA_AG_AT_SET,  BTA_AG_AT_INT,   1,   1},
-    {"+BLDN", BTA_AG_AT_BLDN_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR,   0,   0},
-    {"+BVRA", BTA_AG_AT_BVRA_EVT, BTA_AG_AT_SET,  BTA_AG_AT_INT,   0,   1},
-    {"+BRSF", BTA_AG_LOCAL_EVT_BRSF, BTA_AG_AT_SET,  BTA_AG_AT_INT,   0,   BTA_AG_CMD_MAX_VAL},
-    {"+NREC", BTA_AG_AT_NREC_EVT, BTA_AG_AT_SET,  BTA_AG_AT_INT,   0,   0},
-    {"+CNUM", BTA_AG_AT_CNUM_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR,   0,   0},
-    {"+BTRH", BTA_AG_AT_BTRH_EVT, BTA_AG_AT_READ | BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 2},
-    {"+CLCC", BTA_AG_AT_CLCC_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR,   0,   0},
-    {"+COPS", BTA_AG_AT_COPS_EVT, BTA_AG_AT_READ | BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
-    {"+CMEE", BTA_AG_LOCAL_EVT_CMEE, BTA_AG_AT_SET,  BTA_AG_AT_INT,   0,   1},
-    {"+BIA",  BTA_AG_LOCAL_EVT_BIA,  BTA_AG_AT_SET,  BTA_AG_AT_STR,   0,  20},
-    {"+CBC",  BTA_AG_AT_CBC_EVT,  BTA_AG_AT_SET,  BTA_AG_AT_INT,   0, 100},
-    {"+BCC",  BTA_AG_LOCAL_EVT_BCC,  BTA_AG_AT_NONE, BTA_AG_AT_STR,   0,   0},
-    {"+BCS",  BTA_AG_AT_BCS_EVT,  BTA_AG_AT_SET,  BTA_AG_AT_INT,   0, BTA_AG_CMD_MAX_VAL},
-    {"+BIND", BTA_AG_AT_BIND_EVT, BTA_AG_AT_SET | BTA_AG_AT_READ | BTA_AG_AT_TEST, BTA_AG_AT_STR, 0, 0},
-    {"+BIEV", BTA_AG_AT_BIEV_EVT, BTA_AG_AT_SET,  BTA_AG_AT_STR,   0,   0},
-    {"+BAC",  BTA_AG_AT_BAC_EVT,  BTA_AG_AT_SET,  BTA_AG_AT_STR,   0,   0},
-    /* End-of-table marker used to stop lookup iteration */
-    {"", 0, 0, 0, 0, 0}
+    {"+CHLD",   (BTA_AG_AT_SET | BTA_AG_AT_TEST),   BTA_AG_AT_STR,   0,   4},
+    {"+CHUP",   BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
+    {"+CIND",   (BTA_AG_AT_READ | BTA_AG_AT_TEST),  BTA_AG_AT_STR,   0,   0},
+    {"+CLIP",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   1},
+    {"+CMER",   BTA_AG_AT_SET,                      BTA_AG_AT_STR,   0,   0},
+    {"+VTS",    BTA_AG_AT_SET,                      BTA_AG_AT_STR,   0,   0},
+    {"+BINP",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   1,   1},
+    {"+BLDN",   BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
+    {"+BVRA",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   1},
+    {"+BRSF",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   BTA_AG_CMD_MAX_VAL},
+    {"+NREC",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   0},
+    {"+CNUM",   BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
+    {"+BTRH",   (BTA_AG_AT_READ | BTA_AG_AT_SET),   BTA_AG_AT_INT,   0,   2},
+    {"+CLCC",   BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
+    {"+COPS",   (BTA_AG_AT_READ | BTA_AG_AT_SET),   BTA_AG_AT_STR,   0,   0},
+    {"+CMEE",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   1},
+    {"+BIA",    BTA_AG_AT_SET,                      BTA_AG_AT_STR,   0,   20},
+    {"+CBC",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   100},
+    {"+BCC",    BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
+    {"+BCS",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   BTA_AG_CMD_MAX_VAL},
+    {"+BAC",    BTA_AG_AT_SET,                      BTA_AG_AT_STR,   0,   0},
+    {"+BIND",   (BTA_AG_AT_SET | BTA_AG_AT_READ | BTA_AG_AT_TEST),  BTA_AG_AT_STR,   0,   0},
+    {"+BIEV",   BTA_AG_AT_SET,                      BTA_AG_AT_STR,   0,   0},
+    {"",        BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0}
 };
 
 /* AT result code table element */
 typedef struct
 {
-    const char  *result_string;       /* AT result string */
-    size_t      result_id;            /* Local or BTA result id */
-    UINT8       arg_type;             /* whether argument is int or string */
+    const char  *p_res;         /* AT result string */
+    UINT8       fmt;            /* whether argument is int or string */
 } tBTA_AG_RESULT;
 
 /* AT result code argument types */
@@ -134,53 +182,60 @@
 /* Local AT command result codes not defined in bta_ag_api.h */
 enum
 {
-    BTA_AG_LOCAL_RES_FIRST = 0x0100,
-    BTA_AG_LOCAL_RES_OK,
-    BTA_AG_LOCAL_RES_ERROR,
-    BTA_AG_LOCAL_RES_RING,
-    BTA_AG_LOCAL_RES_CLIP,
-    BTA_AG_LOCAL_RES_BRSF,
-    BTA_AG_LOCAL_RES_CMEE,
-    BTA_AG_LOCAL_RES_BCS
+    BTA_AG_RES_OK,
+    BTA_AG_RES_ERROR,
+    BTA_AG_RES_RING,
+    BTA_AG_RES_VGS,
+    BTA_AG_RES_VGM,
+    BTA_AG_RES_CCWA,
+    BTA_AG_RES_CHLD,
+    BTA_AG_RES_CIND,
+    BTA_AG_RES_CLIP,
+    BTA_AG_RES_CIEV,
+    BTA_AG_RES_BINP,
+    BTA_AG_RES_BVRA,
+    BTA_AG_RES_BRSF,
+    BTA_AG_RES_BSIR,
+    BTA_AG_RES_CNUM,
+    BTA_AG_RES_BTRH,
+    BTA_AG_RES_CLCC,
+    BTA_AG_RES_COPS,
+    BTA_AG_RES_CMEE,
+    BTA_AG_RES_BCS,
+    BTA_AG_RES_UNAT,
+    BTA_AG_RES_BIND
 };
 
+#if defined(BTA_HSP_RESULT_REPLACE_COLON) && (BTA_HSP_RESULT_REPLACE_COLON == TRUE)
+#define COLON_IDX_4_VGSVGM    4
+#endif
 /* AT result code constant table */
 const tBTA_AG_RESULT bta_ag_result_tbl[] =
 {
-    {"OK",      BTA_AG_LOCAL_RES_OK,    BTA_AG_RES_FMT_NONE},
-    {"ERROR",   BTA_AG_LOCAL_RES_ERROR, BTA_AG_RES_FMT_NONE},
-    {"RING",    BTA_AG_LOCAL_RES_RING,  BTA_AG_RES_FMT_NONE},
-    {"+VGS: ",  BTA_AG_SPK_RES,         BTA_AG_RES_FMT_INT},
-    {"+VGM: ",  BTA_AG_MIC_RES,         BTA_AG_RES_FMT_INT},
-    {"+CCWA: ", BTA_AG_CALL_WAIT_RES,   BTA_AG_RES_FMT_STR},
-    {"+CHLD: ", BTA_AG_IN_CALL_HELD_RES,BTA_AG_RES_FMT_STR},
-    {"+CIND: ", BTA_AG_CIND_RES,        BTA_AG_RES_FMT_STR},
-    {"+CLIP: ", BTA_AG_LOCAL_RES_CLIP,  BTA_AG_RES_FMT_STR},
-    {"+CIEV: ", BTA_AG_IND_RES,         BTA_AG_RES_FMT_STR},
-    {"+BINP: ", BTA_AG_BINP_RES,        BTA_AG_RES_FMT_STR},
-    {"+BVRA: ", BTA_AG_BVRA_RES,        BTA_AG_RES_FMT_INT},
-    {"+BRSF: ", BTA_AG_LOCAL_RES_BRSF,  BTA_AG_RES_FMT_INT},
-    {"+BSIR: ", BTA_AG_INBAND_RING_RES, BTA_AG_RES_FMT_INT},
-    {"+CNUM: ", BTA_AG_CNUM_RES,        BTA_AG_RES_FMT_STR},
-    {"+BTRH: ", BTA_AG_BTRH_RES,        BTA_AG_RES_FMT_INT},
-    {"+CLCC: ", BTA_AG_CLCC_RES,        BTA_AG_RES_FMT_STR},
-    {"+COPS: ", BTA_AG_COPS_RES,        BTA_AG_RES_FMT_STR},
-    {"+CME ERROR: ", BTA_AG_LOCAL_RES_CMEE, BTA_AG_RES_FMT_INT},
-    {"+BCS: ",  BTA_AG_LOCAL_RES_BCS,   BTA_AG_RES_FMT_INT},
-    {"+BIND: ", BTA_AG_BIND_RES,        BTA_AG_RES_FMT_STR},
-    {"",        BTA_AG_UNAT_RES,        BTA_AG_RES_FMT_STR}
+    {"OK",      BTA_AG_RES_FMT_NONE},
+    {"ERROR",   BTA_AG_RES_FMT_NONE},
+    {"RING",    BTA_AG_RES_FMT_NONE},
+    {"+VGS: ",  BTA_AG_RES_FMT_INT},
+    {"+VGM: ",  BTA_AG_RES_FMT_INT},
+    {"+CCWA: ", BTA_AG_RES_FMT_STR},
+    {"+CHLD: ", BTA_AG_RES_FMT_STR},
+    {"+CIND: ", BTA_AG_RES_FMT_STR},
+    {"+CLIP: ", BTA_AG_RES_FMT_STR},
+    {"+CIEV: ", BTA_AG_RES_FMT_STR},
+    {"+BINP: ", BTA_AG_RES_FMT_STR},
+    {"+BVRA: ", BTA_AG_RES_FMT_INT},
+    {"+BRSF: ", BTA_AG_RES_FMT_INT},
+    {"+BSIR: ", BTA_AG_RES_FMT_INT},
+    {"+CNUM: ", BTA_AG_RES_FMT_STR},
+    {"+BTRH: ", BTA_AG_RES_FMT_INT},
+    {"+CLCC: ", BTA_AG_RES_FMT_STR},
+    {"+COPS: ", BTA_AG_RES_FMT_STR},
+    {"+CME ERROR: ", BTA_AG_RES_FMT_INT},
+    {"+BCS: ",  BTA_AG_RES_FMT_INT},
+    {"",        BTA_AG_RES_FMT_STR},
+    {"+BIND: ", BTA_AG_RES_FMT_STR},
 };
 
-static const tBTA_AG_RESULT* bta_ag_result_by_code(size_t code)
-{
-    for (size_t i = 0; i != sizeof(bta_ag_result_tbl) /
-      sizeof(bta_ag_result_tbl[0]); ++i)
-    {
-        if (code == bta_ag_result_tbl[i].result_id)
-            return &bta_ag_result_tbl[i];
-    }
-    return 0;
-}
 
 const tBTA_AG_AT_CMD *bta_ag_at_tbl[BTA_AG_NUM_IDX] =
 {
@@ -188,31 +243,102 @@
     bta_ag_hfp_cmd
 };
 
-typedef struct
+/* callback event lookup table for HSP */
+const tBTA_AG_EVT bta_ag_hsp_cb_evt[] =
 {
-    size_t result_code;
-    size_t indicator;
-} tBTA_AG_INDICATOR_MAP;
-
-/* callsetup indicator value lookup table */
-const tBTA_AG_INDICATOR_MAP callsetup_indicator_map[] =
-{
-    {BTA_AG_IN_CALL_RES,        BTA_AG_CALLSETUP_INCOMING},
-    {BTA_AG_CALL_WAIT_RES,      BTA_AG_CALLSETUP_INCOMING},
-    {BTA_AG_OUT_CALL_ORIG_RES,  BTA_AG_CALLSETUP_OUTGOING},
-    {BTA_AG_OUT_CALL_ALERT_RES, BTA_AG_CALLSETUP_ALERTING}
+    BTA_AG_AT_CKPD_EVT,     /* BTA_AG_HS_CMD_CKPD */
+    BTA_AG_SPK_EVT,         /* BTA_AG_HS_CMD_VGS */
+    BTA_AG_MIC_EVT          /* BTA_AG_HS_CMD_VGM */
 };
 
-static size_t bta_ag_indicator_by_result_code(size_t code)
+/* callback event lookup table for HFP  (Indexed by command) */
+const tBTA_AG_EVT bta_ag_hfp_cb_evt[] =
 {
-    for (size_t i = 0; i != sizeof(callsetup_indicator_map) /
-      sizeof(callsetup_indicator_map[0]); ++i)
-    {
-        if (code == callsetup_indicator_map[i].result_code)
-            return callsetup_indicator_map[i].indicator;
-    }
-    return BTA_AG_CALLSETUP_NONE;
-}
+    BTA_AG_AT_A_EVT,        /* BTA_AG_HF_CMD_A */
+    BTA_AG_AT_D_EVT,        /* BTA_AG_HF_CMD_D */
+    BTA_AG_SPK_EVT,         /* BTA_AG_HF_CMD_VGS */
+    BTA_AG_MIC_EVT,         /* BTA_AG_HF_CMD_VGM */
+    0,                      /* BTA_AG_HF_CMD_CCWA */
+    BTA_AG_AT_CHLD_EVT,     /* BTA_AG_HF_CMD_CHLD */
+    BTA_AG_AT_CHUP_EVT,     /* BTA_AG_HF_CMD_CHUP */
+    BTA_AG_AT_CIND_EVT,     /* BTA_AG_HF_CMD_CIND */
+    0,                      /* BTA_AG_HF_CMD_CLIP */
+    0,                      /* BTA_AG_HF_CMD_CMER */
+    BTA_AG_AT_VTS_EVT,      /* BTA_AG_HF_CMD_VTS */
+    BTA_AG_AT_BINP_EVT,     /* BTA_AG_HF_CMD_BINP */
+    BTA_AG_AT_BLDN_EVT,     /* BTA_AG_HF_CMD_BLDN */
+    BTA_AG_AT_BVRA_EVT,     /* BTA_AG_HF_CMD_BVRA */
+    0,                      /* BTA_AG_HF_CMD_BRSF */
+    BTA_AG_AT_NREC_EVT,     /* BTA_AG_HF_CMD_NREC */
+    BTA_AG_AT_CNUM_EVT,     /* BTA_AG_HF_CMD_CNUM */
+    BTA_AG_AT_BTRH_EVT,     /* BTA_AG_HF_CMD_BTRH */
+    BTA_AG_AT_CLCC_EVT,     /* BTA_AG_HF_CMD_CLCC */
+    BTA_AG_AT_COPS_EVT,     /* BTA_AG_HF_CMD_COPS */
+    0,                      /* BTA_AG_HF_CMD_CMEE */
+    0,                      /* BTA_AG_HF_CMD_BIA */
+    BTA_AG_AT_CBC_EVT,      /* BTA_AG_HF_CMD_CBC */
+    0,                      /* BTA_AG_HF_CMD_BCC */
+    BTA_AG_AT_BCS_EVT,      /* BTA_AG_HF_CMD_BCS */
+    BTA_AG_AT_BAC_EVT,      /* BTA_AG_HF_CMD_BAC */
+    BTA_AG_AT_BIND_EVT,     /* BTA_AG_HF_CMD_BIND */
+    BTA_AG_AT_BIEV_EVT      /* BTA_AG_HF_CMD_BIEV */
+};
+
+/* translation of API result code values to internal values */
+const UINT8 bta_ag_trans_result[] =
+{
+    BTA_AG_RES_VGS,     /* BTA_AG_SPK_RES */
+    BTA_AG_RES_VGM,     /* BTA_AG_MIC_RES */
+    BTA_AG_RES_BSIR,    /* BTA_AG_INBAND_RING_RES */
+    BTA_AG_RES_CIND,    /* BTA_AG_CIND_RES */
+    BTA_AG_RES_BINP,    /* BTA_AG_BINP_RES */
+    BTA_AG_RES_CIEV,    /* BTA_AG_IND_RES */
+    BTA_AG_RES_BVRA,    /* BTA_AG_BVRA_RES */
+    BTA_AG_RES_CNUM,    /* BTA_AG_CNUM_RES */
+    BTA_AG_RES_BTRH,    /* BTA_AG_BTRH_RES */
+    BTA_AG_RES_CLCC,    /* BTA_AG_CLCC_RES */
+    BTA_AG_RES_COPS,    /* BTA_AG_COPS_RES */
+    0,                  /* BTA_AG_IN_CALL_RES */
+    0,                  /* BTA_AG_IN_CALL_CONN_RES */
+    BTA_AG_RES_CCWA,    /* BTA_AG_CALL_WAIT_RES */
+    0,                  /* BTA_AG_OUT_CALL_ORIG_RES */
+    0,                  /* BTA_AG_OUT_CALL_ALERT_RES */
+    0,                  /* BTA_AG_OUT_CALL_CONN_RES */
+    0,                  /* BTA_AG_CALL_CANCEL_RES */
+    0,                  /* BTA_AG_END_CALL_RES */
+    0,                  /* BTA_AG_IN_CALL_HELD_RES */
+    BTA_AG_RES_UNAT,    /* BTA_AG_UNAT_RES */
+    0,                  /* BTA_AG_MULTI_CALL_RES */
+    BTA_AG_RES_BIND     /* BTA_AG_BIND_RES */
+};
+
+/* callsetup indicator value lookup table */
+const UINT8 bta_ag_callsetup_ind_tbl[] =
+{
+    0,                          /* BTA_AG_SPK_RES */
+    0,                          /* BTA_AG_MIC_RES */
+    0,                          /* BTA_AG_INBAND_RING_RES */
+    0,                          /* BTA_AG_CIND_RES */
+    0,                          /* BTA_AG_BINP_RES */
+    0,                          /* BTA_AG_IND_RES */
+    0,                          /* BTA_AG_BVRA_RES */
+    0,                          /* BTA_AG_CNUM_RES */
+    0,                          /* BTA_AG_BTRH_RES */
+    0,                          /* BTA_AG_CLCC_RES */
+    0,                          /* BTA_AG_COPS_RES */
+    BTA_AG_CALLSETUP_INCOMING,  /* BTA_AG_IN_CALL_RES */
+    BTA_AG_CALLSETUP_NONE,      /* BTA_AG_IN_CALL_CONN_RES */
+    BTA_AG_CALLSETUP_INCOMING,  /* BTA_AG_CALL_WAIT_RES */
+    BTA_AG_CALLSETUP_OUTGOING,  /* BTA_AG_OUT_CALL_ORIG_RES */
+    BTA_AG_CALLSETUP_ALERTING,  /* BTA_AG_OUT_CALL_ALERT_RES */
+    BTA_AG_CALLSETUP_NONE,      /* BTA_AG_OUT_CALL_CONN_RES */
+    BTA_AG_CALLSETUP_NONE,      /* BTA_AG_CALL_CANCEL_RES */
+    BTA_AG_CALLSETUP_NONE,      /* BTA_AG_END_CALL_RES */
+    BTA_AG_CALLSETUP_NONE,      /* BTA_AG_IN_CALL_HELD_RES */
+    0,                          /* BTA_AG_UNAT_RES */
+    0,                          /* BTA_AG_MULTI_CALL_RES */
+    0,                          /* BTA_AG_BIND_RES */
+};
 
 /*******************************************************************************
 **
@@ -224,50 +350,49 @@
 ** Returns          void
 **
 *******************************************************************************/
-static void bta_ag_send_result(tBTA_AG_SCB *p_scb, size_t code, char *p_arg,
+static void bta_ag_send_result(tBTA_AG_SCB *p_scb, UINT8 code, char *p_arg,
                                INT16 int_arg)
 {
-    const tBTA_AG_RESULT *result = bta_ag_result_by_code(code);
-    if (result == 0)
-    {
-        LOG_ERROR(LOG_TAG, "%s Unable to lookup result for code %zu", __func__, code);
-        return;
-    }
 
     char buf[BTA_AG_AT_MAX_LEN + 16];
     char *p = buf;
-    memset(buf, 0, sizeof(buf));
-
+    UINT16  len;
+#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
+    memset(buf, NULL, sizeof(buf));
+#endif
     /* init with \r\n */
     *p++ = '\r';
     *p++ = '\n';
 
     /* copy result code string */
-    strlcpy(p, result->result_string, sizeof(buf) - 2);
-
+    strlcpy(p, bta_ag_result_tbl[code].p_res, sizeof(buf) - 2);
+#if defined(BTA_HSP_RESULT_REPLACE_COLON) && (BTA_HSP_RESULT_REPLACE_COLON == TRUE)
     if (p_scb->conn_service == BTA_AG_HSP)
     {
         /* If HSP then ":"symbol should be changed as "=" for HSP compatibility */
         switch(code)
         {
-        case BTA_AG_SPK_RES:
-        case BTA_AG_MIC_RES:
+        case BTA_AG_RES_VGS:
+        case BTA_AG_RES_VGM:
             if(*(p+COLON_IDX_4_VGSVGM) == ':')
             {
+                #if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
+                APPL_TRACE_DEBUG("[HSP] ':'symbol is changed as '=' for HSP compatibility");
+                #endif
                 *(p+COLON_IDX_4_VGSVGM) = '=';
             }
             break;
         }
     }
-
-    p += strlen(result->result_string);
+#endif
+    p += strlen(bta_ag_result_tbl[code].p_res);
 
     /* copy argument if any */
-    if (result->arg_type == BTA_AG_RES_FMT_INT)
+    if (bta_ag_result_tbl[code].fmt == BTA_AG_RES_FMT_INT)
     {
         p += utl_itoa((UINT16) int_arg, p);
     }
-    else if (result->arg_type == BTA_AG_RES_FMT_STR)
+    else if (bta_ag_result_tbl[code].fmt == BTA_AG_RES_FMT_STR)
     {
         strcpy(p, p_arg);
         p += strlen(p_arg);
@@ -277,11 +402,79 @@
     *p++ = '\r';
     *p++ = '\n';
 
+#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
+    APPL_TRACE_IMP("bta_ag_send_result: %s", buf);
+#endif
+
     /* send to RFCOMM */
-    UINT16 len = 0;
     PORT_WriteData(p_scb->conn_handle, buf, (UINT16) (p - buf), &len);
 }
 
+#if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_ag_send_multi_result
+**
+** Description      Send multiple AT result codes.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_send_multi_result(tBTA_AG_SCB *p_scb, tBTA_AG_MULTI_RESULT_CB *m_res_cb)
+{
+    char    buf[BTA_AG_AT_MAX_LEN * BTA_AG_AT_MULTI_LEN + 16];
+    char    *p = buf;
+    UINT16  len;
+    UINT8   res_idx = 0;
+
+    if((!m_res_cb) || (m_res_cb->num_result == 0) || (m_res_cb->num_result > BTA_AG_AT_MULTI_LEN))
+    {
+        APPL_TRACE_DEBUG("m_res_cb is NULL or num_result is out of range.");
+        return;
+    }
+
+#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
+    memset(buf, NULL, sizeof(buf));
+#endif
+
+    while(res_idx < m_res_cb->num_result)
+    {
+        /* init with \r\n */
+        *p++ = '\r';
+        *p++ = '\n';
+
+        /* copy result code string */
+        strcpy(p, bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].p_res);
+        p += strlen(bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].p_res);
+
+        /* copy argument if any */
+        if (bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].fmt == BTA_AG_RES_FMT_INT)
+        {
+            p += utl_itoa((UINT16) m_res_cb->res_cb[res_idx].int_arg, p);
+        }
+        else if (bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].fmt == BTA_AG_RES_FMT_STR)
+        {
+            strcpy(p, m_res_cb->res_cb[res_idx].p_arg);
+            p += strlen(m_res_cb->res_cb[res_idx].p_arg);
+        }
+
+        /* finish with \r\n */
+        *p++ = '\r';
+        *p++ = '\n';
+
+        res_idx++;
+    }
+
+#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
+    APPL_TRACE_DEBUG("send_result: %s", buf);
+#endif
+
+    /* send to RFCOMM */
+    PORT_WriteData(p_scb->conn_handle, buf, (UINT16) (p - buf), &len);
+}
+#endif
+
 /*******************************************************************************
 **
 ** Function         bta_ag_send_ok
@@ -294,7 +487,7 @@
 *******************************************************************************/
 static void bta_ag_send_ok(tBTA_AG_SCB *p_scb)
 {
-    bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_OK, NULL, 0);
+    bta_ag_send_result(p_scb, BTA_AG_RES_OK, NULL, 0);
 }
 
 /*******************************************************************************
@@ -312,9 +505,9 @@
 {
     /* If HFP and extended audio gateway error codes are enabled */
     if (p_scb->conn_service == BTA_AG_HFP && p_scb->cmee_enabled)
-        bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_CMEE, NULL, errcode);
+        bta_ag_send_result(p_scb, BTA_AG_RES_CMEE, NULL, errcode);
     else
-        bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_ERROR, NULL, 0);
+        bta_ag_send_result(p_scb, BTA_AG_RES_ERROR, NULL, 0);
 }
 
 /*******************************************************************************
@@ -399,7 +592,7 @@
         p += utl_itoa(id, p);
         *p++ = ',';
         utl_itoa(value, p);
-        bta_ag_send_result(p_scb, BTA_AG_IND_RES, str, 0);
+        bta_ag_send_result(p_scb, BTA_AG_RES_CIEV, str, 0);
     }
 }
 
@@ -487,6 +680,68 @@
     return (retval);
 }
 
+/*******************************************************************************
+**
+** Function         bta_ag_parse_biev
+**
+** Description      Parse AT+BIEV parameter string.
+**
+**
+** Returns          TRUE if parsed ok, FALSE otherwise.
+**
+*******************************************************************************/
+static BOOLEAN bta_ag_parse_biev(tBTA_AG_SCB *p_scb, char *p_s)
+ {
+     INT32 token1;
+     long long int token2;
+     BOOLEAN cont = FALSE;       /* Continue processing */
+     char *p, *end;
+     int i = 0;
+
+     while(p_s)
+     {
+         /* skip to comma delimiter */
+         for(p = p_s; *p != ',' && *p != 0; p++);
+
+         /* get integer value */
+         if (*p != 0)
+         {
+             *p = 0;
+             cont = TRUE;
+         }
+         else
+             cont = FALSE;
+
+         if (i > 1)
+             return FALSE;
+
+         if (i == 0)
+         {
+             token1 = utl_str2int32(p_s);
+             if (token1 == -1)
+                 return FALSE;
+         }
+         else
+         {
+            token2 = strtoll(p_s, &end, 10);
+            if (*end != 0 || token2 < 0 || token2 > 0xFFFFFFFF)
+               return FALSE;
+         }
+
+         if (cont)
+         {
+             p_s = p + 1;
+             i++;
+         }
+         else
+         {
+             if (i == 0) return FALSE;
+             break;
+         }
+     }
+     return TRUE;
+ }
+
 #if (BTM_WBS_INCLUDED == TRUE )
 /*******************************************************************************
 **
@@ -545,6 +800,61 @@
 
 /*******************************************************************************
 **
+** Function         bta_ag_parse_bind
+**
+** Description      Parse AT+BIND parameter string.
+**
+** Returns          TRUE if parsed ok, FALSE otherwise.
+**
+*******************************************************************************/
+static BOOLEAN bta_ag_parse_bind(tBTA_AG_SCB *p_scb, char *p_s)
+{
+    INT32  anum_hfind;
+    BOOLEAN cont = FALSE;       /* Continue processing */
+    char *p;
+    int i = 0;
+
+    while(p_s)
+    {
+        /* skip to comma delimiter */
+        for(p = p_s; *p != ',' && *p != 0; p++);
+
+        /* get integre value */
+        if (*p != 0)
+        {
+            *p = 0;
+            cont = TRUE;
+        }
+        else
+            cont = FALSE;
+
+        anum_hfind = utl_str2int32(p_s);
+        if ((anum_hfind == -1) || (i == 20))
+            return FALSE;
+
+        switch(anum_hfind)
+        {
+            case BTA_AG_HFIND_ENHANCED_SAFETY:
+                APPL_TRACE_DEBUG("BTA_AG_HFIND_ENHANCED_SAFETY supported");
+                break;
+            default:
+                APPL_TRACE_ERROR("unknown HFIND");
+                break;
+        }
+
+        if (cont)
+        {
+            p_s = p + 1;
+            i++;
+        }
+        else
+            break;
+    }
+    return TRUE;
+}
+
+/*******************************************************************************
+**
 ** Function         bta_ag_process_unat_res
 **
 ** Description      Process the unat response data and remove extra carriage return
@@ -632,9 +942,10 @@
 void bta_ag_send_call_inds(tBTA_AG_SCB *p_scb, tBTA_AG_RES result)
 {
     UINT8 call = p_scb->call_ind;
+    UINT8 callsetup;
 
     /* set new call and callsetup values based on BTA_AgResult */
-    size_t callsetup = bta_ag_indicator_by_result_code(result);
+    callsetup = bta_ag_callsetup_ind_tbl[result];
 
     if (result == BTA_AG_END_CALL_RES)
     {
@@ -665,15 +976,16 @@
 ** Returns          void
 **
 *******************************************************************************/
-void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 command_id, UINT8 arg_type,
+void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
                                 char *p_arg, char *p_end, INT16 int_arg)
 {
-    APPL_TRACE_DEBUG("AT cmd:%d arg_type:%d arg:%d arg:%s", command_id, arg_type,
+    tBTA_AG_VAL val;
+    APPL_TRACE_DEBUG("AT cmd:%d arg_type:%d arg:%d arg:%s", cmd, arg_type,
                       int_arg, p_arg);
 
+    /* send OK */
     bta_ag_send_ok(p_scb);
 
-    tBTA_AG_VAL val;
     val.hdr.handle = bta_ag_scb_to_idx(p_scb);
     val.hdr.app_id = p_scb->app_id;
     val.num = (UINT16) int_arg;
@@ -687,225 +999,8 @@
     strlcpy(val.str, p_arg, sizeof(val.str));
 
     /* call callback with event */
-    (*bta_ag_cb.p_cback)(command_id, (tBTA_AG *) &val);
+    (*bta_ag_cb.p_cback)(bta_ag_hsp_cb_evt[cmd], (tBTA_AG *) &val);
 }
-
-/*******************************************************************************
-**
-** Function         bta_ag_find_empty_hf_ind)
-**
-** Description      This function returns the index of an empty HF indicator
-**                  structure.
-**
-** Returns          int : index of the empty HF indicator structure or
-**                            -1 if no empty indicator
-**                            is available.
-**
-*******************************************************************************/
-static int bta_ag_find_empty_hf_ind(tBTA_AG_SCB *p_scb)
-{
-    for (int index = 0; index < BTA_AG_MAX_NUM_PEER_HF_IND; index++)
-    {
-        if (p_scb->peer_hf_indicators[index].ind_id == 0)
-            return index;
-    }
-
-    return -1;
-}
-
-
-/*******************************************************************************
-**
-** Function         bta_ag_find_hf_ind_by_id
-**
-** Description      This function returns the index of the HF indicator
-**                  structure by the indicator id
-**
-** Returns          int : index of the HF indicator structure
-**                            -1 if the indicator
-**                            was not found.
-**
-*******************************************************************************/
-static int bta_ag_find_hf_ind_by_id(tBTA_AG_HF_IND *p_hf_ind, int size, uint32_t ind_id)
-{
-    for (int index = 0; index < size; index++)
-    {
-        if (p_hf_ind[index].ind_id == ind_id)
-            return index;
-    }
-
-    return -1;
-}
-
-/*******************************************************************************
-**
-** Function         bta_ag_parse_bind_set
-**
-** Description      Parse AT+BIND set command and save the indicators
-**
-** Returns          true if successful
-**
-*******************************************************************************/
-static bool bta_ag_parse_bind_set(tBTA_AG_SCB *p_scb, tBTA_AG_VAL val)
-{
-    char *p_token = strtok(val.str, ",");
-    if (p_token == NULL)
-        return false;
-
-    while (p_token != NULL)
-    {
-        uint16_t rcv_ind_id = atoi(p_token);
-        int index = bta_ag_find_empty_hf_ind(p_scb);
-        if (index == -1)
-        {
-            APPL_TRACE_WARNING("%s Can't save more indicators", __func__);
-            return false;
-        }
-
-        p_scb->peer_hf_indicators[index].ind_id = rcv_ind_id;
-        APPL_TRACE_DEBUG("%s peer_hf_ind[%d] = %d", __func__, index, rcv_ind_id);
-
-        p_token = strtok(NULL, ",");
-    }
-
-    return true;
-}
-
-/*******************************************************************************
-**
-** Function         bta_ag_bind_response
-**
-** Description      Send response for the AT+BIND command (HFP 1.7) received
-**                  from the headset based on the argument types.
-**
-** Returns          Void
-**
-*******************************************************************************/
-static void bta_ag_bind_response(tBTA_AG_SCB *p_scb, uint8_t arg_type)
-{
-    char buffer[BTA_AG_AT_MAX_LEN];
-    memset(buffer, 0, BTA_AG_AT_MAX_LEN);
-
-    if (arg_type == BTA_AG_AT_TEST)
-    {
-        int index = 0;
-        buffer[index++] = '(';
-
-        for (uint32_t i = 0; i < bta_ag_local_hf_ind_cfg[0].ind_id; i++)
-        {
-            if (bta_ag_local_hf_ind_cfg[i+1].is_supported == true)
-            {
-                /* Add ',' from second indicator */
-                if (index > 1)
-                    buffer[index++] = ',';
-                sprintf(&buffer[index++], "%d", bta_ag_local_hf_ind_cfg[i+1].ind_id);
-            }
-        }
-
-        buffer[index++] = ')';
-
-        bta_ag_send_result(p_scb, BTA_AG_BIND_RES, buffer, 0);
-        bta_ag_send_ok(p_scb);
-    }
-    else if (arg_type == BTA_AG_AT_READ)
-    {
-        char *p = buffer;
-
-        /* bta_ag_local_hf_ind_cfg[0].ind_id is used as BTA_AG_NUM_LOCAL_HF_IND */
-        for (uint32_t i = 0; i < bta_ag_local_hf_ind_cfg[0].ind_id; i++)
-        {
-            if (i == BTA_AG_MAX_NUM_LOCAL_HF_IND)
-            {
-                APPL_TRACE_WARNING("%s No space for more HF indicators", __func__);
-                break;
-            }
-
-            p_scb->local_hf_indicators[i].ind_id = bta_ag_local_hf_ind_cfg[i+1].ind_id;
-            p_scb->local_hf_indicators[i].is_supported = bta_ag_local_hf_ind_cfg[i+1].is_supported;
-            p_scb->local_hf_indicators[i].is_enable = bta_ag_local_hf_ind_cfg[i+1].is_enable;
-
-            int peer_index = bta_ag_find_hf_ind_by_id(p_scb->peer_hf_indicators,
-                                                    BTA_AG_MAX_NUM_PEER_HF_IND,
-                                                    p_scb->local_hf_indicators[i].ind_id);
-
-            /* Check whether local and peer sides support this indicator */
-            if (p_scb->local_hf_indicators[i].is_supported == true && peer_index != -1)
-            {
-                /* In the format of ind, state */
-                p += utl_itoa((uint16_t) p_scb->local_hf_indicators[i].ind_id, p);
-                *p++ = ',';
-                p += utl_itoa((uint16_t) p_scb->local_hf_indicators[i].is_enable, p);
-
-                bta_ag_send_result(p_scb, BTA_AG_BIND_RES, buffer, 0);
-
-                memset(buffer, 0, sizeof(buffer));
-                p = buffer;
-            } else {
-                /* If indicator is not supported, also set it to disable */
-                p_scb->local_hf_indicators[i].is_enable = false;
-            }
-        }
-
-        bta_ag_send_ok(p_scb);
-
-        /* If the service level connection wan't already open, now it's open */
-        if (!p_scb->svc_conn)
-            bta_ag_svc_conn_open(p_scb, NULL);
-    }
-}
-
-/*******************************************************************************
-**
-** Function         bta_ag_parse_biev_response
-**
-** Description      Send response for AT+BIEV command (HFP 1.7) received from
-**                  the headset based on the argument types.
-**
-** Returns          true if the response was parsed successfully
-**
-*******************************************************************************/
-static bool bta_ag_parse_biev_response(tBTA_AG_SCB *p_scb, tBTA_AG_VAL *val)
-{
-    char *p_token = strtok(val->str, ",");
-    uint16_t rcv_ind_id = atoi(p_token);
-
-    p_token = strtok(NULL, ",");
-    uint16_t rcv_ind_val = atoi(p_token);
-
-    APPL_TRACE_DEBUG("%s BIEV indicator id %d, value %d", __func__, rcv_ind_id, rcv_ind_val);
-
-    /* Check whether indicator ID is valid or not */
-    if (rcv_ind_id > BTA_AG_NUM_LOCAL_HF_IND)
-    {
-        APPL_TRACE_WARNING("%s received invalid indicator id %d", __func__, rcv_ind_id);
-        return false;
-    }
-
-    /* Check this indicator is support or not and enabled or not */
-    int local_index = bta_ag_find_hf_ind_by_id(p_scb->local_hf_indicators,
-                                BTA_AG_MAX_NUM_LOCAL_HF_IND, rcv_ind_id);
-    if (local_index == -1 ||
-        p_scb->local_hf_indicators[local_index].is_supported != true ||
-        p_scb->local_hf_indicators[local_index].is_enable != true)
-    {
-        APPL_TRACE_WARNING("%s indicator id %d not supported or disabled", __func__, rcv_ind_id);
-        return false;
-    }
-
-    /* For each indicator ID, check whether the indicator value is in range */
-    if (rcv_ind_val < bta_ag_local_hf_ind_cfg[rcv_ind_id].ind_min_val ||
-        rcv_ind_val > bta_ag_local_hf_ind_cfg[rcv_ind_id].ind_max_val)
-    {
-        APPL_TRACE_WARNING("%s invalid ind_val %d", __func__, rcv_ind_val);
-        return false;
-    }
-
-    val->lidx = rcv_ind_id;
-    val->num = rcv_ind_val;
-
-    return true;
-}
-
 /*******************************************************************************
 **
 ** Function         bta_ag_at_hfp_cback
@@ -920,9 +1015,12 @@
                                 char *p_arg, char *p_end, INT16 int_arg)
 {
     tBTA_AG_VAL     val;
+    tBTA_AG_EVT   event;
     tBTA_AG_SCB     *ag_scb;
     UINT32          i, ind_id;
     UINT32          bia_masked_out;
+    tBTA_AG_FEAT  features;
+    char value[PROPERTY_VALUE_MAX];
 #if (BTM_WBS_INCLUDED == TRUE )
     tBTA_AG_PEER_CODEC  codec_type, codec_sent;
 #endif
@@ -933,13 +1031,11 @@
         return;
     }
 
-    APPL_TRACE_DEBUG("HFP AT cmd:%d arg_type:%d arg:%d arg:%s", cmd, arg_type,
+    APPL_TRACE_IMP("HFP AT cmd:%d arg_type:%d arg:%d arg:%s", cmd, arg_type,
                       int_arg, p_arg);
 
-    memset(&val, 0, sizeof(tBTA_AG_VAL));
     val.hdr.handle = bta_ag_scb_to_idx(p_scb);
     val.hdr.app_id = p_scb->app_id;
-    val.hdr.status = BTA_AG_SUCCESS;
     val.num = int_arg;
     bdcpy(val.bd_addr, p_scb->peer_addr);
 
@@ -951,33 +1047,25 @@
     }
     strlcpy(val.str, p_arg, sizeof(val.str));
 
-    /**
-     * Unless this this is a local event, by default we'll forward
-     * the event code to the application.
-     * If |event| is 0 at the end of this function, the application
-     * callback is NOT invoked.
-     */
-    tBTA_AG_EVT event = 0;
-    if (cmd < BTA_AG_LOCAL_EVT_FIRST)
-        event = cmd;
+    event = bta_ag_hfp_cb_evt[cmd];
 
     switch (cmd)
     {
-        case BTA_AG_AT_A_EVT:
-        case BTA_AG_SPK_EVT:
-        case BTA_AG_MIC_EVT:
-        case BTA_AG_AT_CHUP_EVT:
-        case BTA_AG_AT_CBC_EVT:
+        case BTA_AG_HF_CMD_A:
+        case BTA_AG_HF_CMD_VGS:
+        case BTA_AG_HF_CMD_VGM:
+        case BTA_AG_HF_CMD_CHUP:
+        case BTA_AG_HF_CMD_CBC:
             /* send OK */
             bta_ag_send_ok(p_scb);
             break;
 
-        case BTA_AG_AT_BLDN_EVT:
+        case BTA_AG_HF_CMD_BLDN:
             /* Do not send OK, App will send error or OK depending on
             ** last dial number enabled or not */
             break;
 
-        case BTA_AG_AT_D_EVT:
+        case BTA_AG_HF_CMD_D:
             /* Do not send OK for Dial cmds
             ** Let application decide whether to send OK or ERROR*/
 
@@ -1011,7 +1099,7 @@
             }
             break;
 
-        case BTA_AG_LOCAL_EVT_CCWA:
+        case BTA_AG_HF_CMD_CCWA:
             /* store setting */
             p_scb->ccwa_enabled = (BOOLEAN) int_arg;
 
@@ -1019,7 +1107,7 @@
             bta_ag_send_ok(p_scb);
             break;
 
-        case BTA_AG_AT_CHLD_EVT:
+        case BTA_AG_HF_CMD_CHLD:
             if (arg_type == BTA_AG_AT_TEST)
             {
                 /* don't call callback */
@@ -1030,17 +1118,23 @@
                 if ((p_scb->peer_version >= HFP_VERSION_1_5) &&
                     (p_scb->features & BTA_AG_FEAT_ECC) &&
                     (p_scb->peer_features & BTA_AG_PEER_FEAT_ECC))
-                    bta_ag_send_result(p_scb, BTA_AG_IN_CALL_HELD_RES,
-                                       p_bta_ag_cfg->chld_val_ecc, 0);
+                    bta_ag_send_result(p_scb, BTA_AG_RES_CHLD, p_bta_ag_cfg->chld_val_ecc, 0);
                 else
-                    bta_ag_send_result(p_scb, BTA_AG_IN_CALL_HELD_RES,
-                                       p_bta_ag_cfg->chld_val, 0);
+                    bta_ag_send_result(p_scb, BTA_AG_RES_CHLD, p_bta_ag_cfg->chld_val, 0);
 
                 /* send OK */
                 bta_ag_send_ok(p_scb);
 
-                /* if service level conn. not already open, now it's open */
-                bta_ag_svc_conn_open(p_scb, NULL);
+                /* if service level conn. not already open and our features and
+                  ** peer features do not have Hf indicators, service level conn. now open
+                  */
+                if (!p_scb->svc_conn &&
+                    !((p_scb->features & BTA_AG_FEAT_HFIND) &&
+                    (p_scb->peer_features & BTA_AG_PEER_FEAT_HFIND)))
+                {
+                    bta_ag_svc_conn_open(p_scb, NULL);
+                }
+
             }
             else
             {
@@ -1084,66 +1178,38 @@
             }
             break;
 
-        case BTA_AG_AT_BIND_EVT:
-            APPL_TRACE_DEBUG("%s BTA_AG_AT_BIND_EVT arg_type: %d", __func__, arg_type);
-            if (arg_type == BTA_AG_AT_SET)
-            {
-                if (bta_ag_parse_bind_set(p_scb, val))
-                {
-                    bta_ag_send_ok(p_scb);
-                } else {
-                    event = 0;/* don't call callback */
-                    bta_ag_send_error(p_scb, BTA_AG_ERR_INVALID_INDEX);
-                }
-            } else {
-                bta_ag_bind_response(p_scb, arg_type);
-
-                /* Need not pass this command beyond BTIF.*/
-                /* Stack handles it internally */
-                event = 0;/* don't call callback */
-            }
-            break;
-
-        case BTA_AG_AT_BIEV_EVT:
-            if (bta_ag_parse_biev_response(p_scb, &val))
-            {
-                bta_ag_send_ok(p_scb);
-            } else {
-                bta_ag_send_error(p_scb, BTA_AG_ERR_INVALID_INDEX);
-                /* don't call callback receiving invalid indicator */
-                event = 0;
-            }
-            break;
-
-        case BTA_AG_AT_CIND_EVT:
+        case BTA_AG_HF_CMD_CIND:
             if (arg_type == BTA_AG_AT_TEST)
             {
                 /* don't call callback */
                 event = 0;
 
                 /* send CIND string, send OK */
-                bta_ag_send_result(p_scb, BTA_AG_CIND_RES, p_bta_ag_cfg->cind_info, 0);
+                bta_ag_send_result(p_scb, BTA_AG_RES_CIND, p_bta_ag_cfg->cind_info, 0);
                 bta_ag_send_ok(p_scb);
             }
             break;
 
-        case BTA_AG_LOCAL_EVT_CLIP:
+        case BTA_AG_HF_CMD_CLIP:
             /* store setting, send OK */
             p_scb->clip_enabled = (BOOLEAN) int_arg;
             bta_ag_send_ok(p_scb);
             break;
 
-        case BTA_AG_LOCAL_EVT_CMER:
+        case BTA_AG_HF_CMD_CMER:
             /* if parsed ok store setting, send OK */
             if (bta_ag_parse_cmer(p_arg, p_end, &p_scb->cmer_enabled))
             {
                 bta_ag_send_ok(p_scb);
 
                 /* if service level conn. not already open and our features and
-                ** peer features do not have 3-way, service level conn. now open
+                ** peer features do not have 3-way and Hf indicators, service level conn. now open
                 */
                 if (!p_scb->svc_conn &&
-                    !((p_scb->features & BTA_AG_FEAT_3WAY) && (p_scb->peer_features & BTA_AG_PEER_FEAT_3WAY)))
+                    !((p_scb->features & BTA_AG_FEAT_3WAY) &&
+                      (p_scb->peer_features & BTA_AG_PEER_FEAT_3WAY)) &&
+                    !((p_scb->features & BTA_AG_FEAT_HFIND) &&
+                      (p_scb->peer_features & BTA_AG_PEER_FEAT_HFIND)))
                 {
                     bta_ag_svc_conn_open(p_scb, NULL);
                 }
@@ -1154,7 +1220,7 @@
             }
             break;
 
-        case BTA_AG_AT_VTS_EVT:
+        case BTA_AG_HF_CMD_VTS:
             /* check argument */
             if (strlen(p_arg) == 1)
             {
@@ -1167,7 +1233,7 @@
             }
             break;
 
-        case BTA_AG_AT_BINP_EVT:
+        case BTA_AG_HF_CMD_BINP:
             /* if feature not set don't call callback, send ERROR */
             if (!(p_scb->features & BTA_AG_FEAT_VTAG))
             {
@@ -1176,7 +1242,7 @@
             }
             break;
 
-        case BTA_AG_AT_BVRA_EVT:
+        case BTA_AG_HF_CMD_BVRA:
             /* if feature not supported don't call callback, send ERROR. App will send OK */
             if (!(p_scb->features & BTA_AG_FEAT_VREC))
             {
@@ -1185,27 +1251,75 @@
             }
             break;
 
-        case BTA_AG_LOCAL_EVT_BRSF:
-        {
-            /* store peer features */
-            p_scb->peer_features = (uint16_t) int_arg;
-
-            tBTA_AG_FEAT features = p_scb->features;
-            if (p_scb->peer_version < HFP_VERSION_1_7)
+        case BTA_AG_HF_CMD_BRSF:
+            /* store peer features. */
+            p_scb->peer_features = (UINT16) int_arg;
+            features = p_scb->features & BTA_AG_BSRF_FEAT_SPEC;
+            if (interop_match_addr(INTEROP_DISABLE_HF_INDICATOR,
+                                   (const bt_bdaddr_t*)p_scb->peer_addr))
             {
-                features &= HFP_1_6_FEAT_MASK;
+                if ((p_scb->peer_version < HFP_VERSION_1_7) &&
+                     (p_scb->peer_features & BTA_AG_PEER_FEAT_HFIND))
+                {
+                    APPL_TRACE_WARNING("hf indicator needs hfp 1.7 support,"
+                                       "thus remove remote device HF indicator bit");
+                    p_scb->peer_features = p_scb->peer_features &(~BTA_AG_PEER_FEAT_HFIND);
+                }
+            }
+            /* if the devices does not support HFP 1.7, report DUT's HFP version as 1.6 */
+            if ((p_scb->peer_version < HFP_VERSION_1_7) &&
+                 (!(p_scb->peer_features & BTA_AG_PEER_FEAT_HFIND)))
+            {
+                /* For PTS keep flags as is. */
+                if (property_get("bt.pts.certification", value, "false") &&
+                    strcmp(value, "true") != 0)
+                {
+                    features = features & ~(BTA_AG_FEAT_HFIND | BTA_AG_FEAT_S4);
+                }
+             }
+             else if ((p_scb->peer_version == HFP_VERSION_1_7) &&
+                      (!(p_scb->peer_features & BTA_AG_PEER_FEAT_HFIND)))
+             {
+                APPL_TRACE_WARNING("%s: Remote is hfp 1.7 but does not support HF indicators" \
+                                     "unset hf indicator bit from BRSF", __func__);
+                /* For PTS keep flags as is. */
+                if (property_get("bt.pts.certification", value, "false") &&
+                    strcmp(value, "true") != 0)
+                {
+                    features = features & ~(BTA_AG_FEAT_HFIND);
+                }
             }
 
-            APPL_TRACE_DEBUG("%s BRSF HF: 0x%x, phone: 0x%x", __func__,
-                p_scb->peer_features, features);
+            bt_property_t prop_name;
+            bt_bdname_t bdname;
+            BOOLEAN remote_name = FALSE;
 
+            BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_BDNAME,
+                    sizeof(bt_bdname_t), &bdname);
+            if (btif_storage_get_remote_device_property((bt_bdaddr_t*)p_scb->peer_addr,
+                    &prop_name) == BT_STATUS_SUCCESS)
+            {
+                remote_name = TRUE;
+            }
+
+            if (interop_match_addr(INTEROP_DISABLE_CODEC_NEGOTIATION,
+                    (const bt_bdaddr_t*)p_scb->peer_addr) ||
+                    (remote_name && interop_match_name(INTEROP_DISABLE_CODEC_NEGOTIATION,
+                    (const char *)bdname.name)))
+            {
+                APPL_TRACE_IMP("%s disable codec negotiation for phone, remote" \
+                                  "for blacklisted device", __func__);
+                features = features & ~(BTA_AG_FEAT_CODEC);
+                p_scb->peer_features = p_scb->peer_features & ~(BTA_AG_PEER_FEAT_CODEC);
+
+            }
             /* send BRSF, send OK */
-            bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_BRSF, NULL, (int16_t) features);
+            bta_ag_send_result(p_scb, BTA_AG_RES_BRSF, NULL,
+                               (INT16) features);
             bta_ag_send_ok(p_scb);
             break;
-        }
 
-        case BTA_AG_AT_NREC_EVT:
+        case BTA_AG_HF_CMD_NREC:
             /* if feature send OK, else don't call callback, send ERROR */
             if (p_scb->features & BTA_AG_FEAT_ECNR)
             {
@@ -1218,7 +1332,7 @@
             }
             break;
 
-        case BTA_AG_AT_BTRH_EVT:
+        case BTA_AG_HF_CMD_BTRH:
             /* if feature send BTRH, send OK:, else don't call callback, send ERROR */
             if (p_scb->features & BTA_AG_FEAT_BTRH)
             {
@@ -1229,7 +1343,7 @@
                     {
                         if (ag_scb->in_use)
                         {
-                            bta_ag_send_result(ag_scb, BTA_AG_BTRH_RES, NULL, int_arg);
+                            bta_ag_send_result(ag_scb, BTA_AG_RES_BTRH, NULL, int_arg);
                         }
                     }
                     bta_ag_send_ok(p_scb);
@@ -1246,7 +1360,7 @@
             }
             break;
 
-        case BTA_AG_AT_COPS_EVT:
+        case BTA_AG_HF_CMD_COPS:
             if (arg_type == BTA_AG_AT_SET)
             {
                 /* don't call callback */
@@ -1257,7 +1371,7 @@
             }
             break;
 
-        case BTA_AG_LOCAL_EVT_CMEE:
+        case BTA_AG_HF_CMD_CMEE:
             if (p_scb->features & BTA_AG_FEAT_EXTERR)
             {
                 /* store setting */
@@ -1274,7 +1388,7 @@
             event = 0;
             break;
 
-        case BTA_AG_LOCAL_EVT_BIA:
+        case BTA_AG_HF_CMD_BIA:
             /* don't call callback */
             event = 0;
 
@@ -1306,10 +1420,10 @@
                 bta_ag_send_error (p_scb, BTA_AG_ERR_INVALID_INDEX);
             break;
 
-        case BTA_AG_AT_CNUM_EVT:
+        case BTA_AG_HF_CMD_CNUM:
             break;
 
-        case BTA_AG_AT_CLCC_EVT:
+        case BTA_AG_HF_CMD_CLCC:
             if(!(p_scb->features & BTA_AG_FEAT_ECS))
             {
                 event = 0;
@@ -1318,7 +1432,7 @@
             break;
 
 #if (BTM_WBS_INCLUDED == TRUE )
-        case BTA_AG_AT_BAC_EVT:
+        case BTA_AG_HF_CMD_BAC:
             bta_ag_send_ok(p_scb);
 
             /* store available codecs from the peer */
@@ -1354,7 +1468,7 @@
             }
             break;
 
-        case BTA_AG_AT_BCS_EVT:
+        case BTA_AG_HF_CMD_BCS:
             bta_ag_send_ok(p_scb);
             alarm_cancel(p_scb->codec_negotiation_timer);
 
@@ -1382,12 +1496,66 @@
             val.num = codec_sent;
             break;
 
-        case BTA_AG_LOCAL_EVT_BCC:
+        case BTA_AG_HF_CMD_BCC:
             bta_ag_send_ok(p_scb);
+            p_scb->codec_updated = TRUE;
             bta_ag_sco_open(p_scb, NULL);
             break;
 #endif
-
+        case BTA_AG_HF_CMD_BIND:
+            if ((p_scb->features & BTA_AG_FEAT_HFIND) &&
+                (p_scb->peer_features & BTA_AG_PEER_FEAT_HFIND))
+            {
+                val.num = arg_type;
+                if (arg_type == BTA_AG_AT_SET)
+                {
+                    if (!bta_ag_parse_bind(p_scb, p_arg))
+                    {
+                        event = 0;
+                        bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
+                    }
+                    else
+                    {
+                        bta_ag_send_ok (p_scb);
+                    }
+                }
+                else if (arg_type == BTA_AG_AT_READ)
+                {
+                    /* open SLC when response ok is sent from app*/
+                    p_scb->slc_pend_open = true;
+                }
+                else if (arg_type == BTA_AG_AT_TEST)
+                {
+                    /* get ag's list of supported hf indicators from app */
+                }
+                else
+                {
+                    event = 0;
+                    bta_ag_send_error (p_scb, BTA_AG_ERR_INVALID_INDEX);
+                }
+            }
+            else
+            {
+                event = 0;
+                bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+            }
+            break;
+        case BTA_AG_HF_CMD_BIEV:
+            if ((p_scb->features & BTA_AG_FEAT_HFIND) &&
+                (p_scb->peer_features & BTA_AG_PEER_FEAT_HFIND))
+            {
+                if (!bta_ag_parse_biev(p_scb, p_arg))
+                {
+                    event = 0;
+                    bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
+                }
+            }
+            else
+            {
+                event = 0;
+                bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+            }
+            break;
         default:
             bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
             break;
@@ -1426,7 +1594,6 @@
     {
         val.hdr.handle = bta_ag_scb_to_idx(p_scb);
         val.hdr.app_id = p_scb->app_id;
-        val.hdr.status = BTA_AG_SUCCESS;
         val.num = 0;
         strlcpy(val.str, p_arg, BTA_AG_AT_MAX_LEN);
         (*bta_ag_cb.p_cback)(BTA_AG_AT_UNAT_EVT, (tBTA_AG *) &val);
@@ -1449,13 +1616,14 @@
 *******************************************************************************/
 void bta_ag_hsp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
 {
+    UINT8 code = bta_ag_trans_result[p_result->result];
     APPL_TRACE_DEBUG("bta_ag_hsp_result : res = %d", p_result->result);
 
     switch(p_result->result)
     {
         case BTA_AG_SPK_RES:
         case BTA_AG_MIC_RES:
-            bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.num);
+            bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
             break;
 
         case BTA_AG_IN_CALL_RES:
@@ -1529,7 +1697,7 @@
             {
                 if (p_result->data.str[0] != 0)
                 {
-                    bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
+                    bta_ag_send_result(p_scb, code, p_result->data.str, 0);
                 }
 
                 if (p_result->data.ok_flag == BTA_AG_OK_DONE)
@@ -1559,13 +1727,15 @@
 *******************************************************************************/
 void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
 {
-    APPL_TRACE_DEBUG("bta_ag_hfp_result : res = %d", p_result->result);
+    UINT8 code = bta_ag_trans_result[p_result->result];
+
+    APPL_TRACE_IMP("bta_ag_hfp_result : res = %d", p_result->result);
 
     switch(p_result->result)
     {
         case BTA_AG_SPK_RES:
         case BTA_AG_MIC_RES:
-            bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.num);
+            bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
             break;
 
         case BTA_AG_IN_CALL_RES:
@@ -1620,6 +1790,16 @@
             */
             bta_ag_send_call_inds(p_scb, p_result->result);
 
+            if (interop_match_addr(INTEROP_DELAY_SCO_FOR_MT_CALL,
+                (const bt_bdaddr_t*)p_scb->peer_addr))
+            {
+               /* Ensure that call active indicator is sent prior to SCO connection
+                  request by adding some delay. Some remotes are very strict in the
+                  order of call indicator and SCO connection request. */
+                APPL_TRACE_IMP("%s: sleeping 20msec before opening sco", __func__);
+                usleep(20*1000);
+            }
+
             if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
             {
                 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
@@ -1722,7 +1902,7 @@
         case BTA_AG_INBAND_RING_RES:
             p_scb->inband_enabled = p_result->data.state;
             APPL_TRACE_DEBUG("inband_enabled set to %d", p_scb->inband_enabled);
-            bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.state);
+            bta_ag_send_result(p_scb, code, NULL, p_result->data.state);
             break;
 
         case BTA_AG_CIND_RES:
@@ -1736,7 +1916,7 @@
             p_scb->callheld_ind = p_result->data.str[12] - '0';
             APPL_TRACE_DEBUG("cind call:%d callsetup:%d", p_scb->call_ind, p_scb->callsetup_ind);
 
-            bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
+            bta_ag_send_result(p_scb, code, p_result->data.str, 0);
             bta_ag_send_ok(p_scb);
             break;
 
@@ -1748,7 +1928,7 @@
             {
                 if (p_result->data.str[0] != 0)
                 {
-                   bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
+                   bta_ag_send_result(p_scb, code, p_result->data.str, 0);
                 }
 
                 if (p_result->data.ok_flag == BTA_AG_OK_DONE)
@@ -1768,11 +1948,18 @@
                 {
                     bta_ag_process_unat_res(p_result->data.str);
                     APPL_TRACE_DEBUG("BTA_AG_RES :%s",p_result->data.str);
-                    bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
+                    bta_ag_send_result(p_scb, code, p_result->data.str, 0);
                 }
 
                 if (p_result->data.ok_flag == BTA_AG_OK_DONE)
                     bta_ag_send_ok(p_scb);
+
+                if (p_scb->slc_pend_open)
+                {
+                    APPL_TRACE_DEBUG("opening SLC now after +BIND READ response");
+                    bta_ag_svc_conn_open(p_scb, NULL);
+                    p_scb->slc_pend_open = FALSE;
+                }
             }
             else
             {
@@ -1783,7 +1970,7 @@
         case BTA_AG_CALL_WAIT_RES:
             if (p_scb->ccwa_enabled)
             {
-                bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
+                bta_ag_send_result(p_scb, code, p_result->data.str, 0);
             }
             bta_ag_send_call_inds(p_scb, p_result->result);
             break;
@@ -1793,7 +1980,7 @@
             break;
 
         case BTA_AG_BVRA_RES:
-            bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.state);
+            bta_ag_send_result(p_scb, code, NULL, p_result->data.state);
             break;
 
         case BTA_AG_BTRH_RES:
@@ -1802,7 +1989,7 @@
                 /* Don't respond to read if not in response & hold state */
                 if (p_result->data.num != BTA_AG_BTRH_NO_RESP)
                 {
-                    bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.num);
+                    bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
                 }
 
                 /* In case of a response to a read request we need to send OK */
@@ -1815,52 +2002,15 @@
             }
             break;
 
-        case BTA_AG_BIND_RES:
-        {
-            /* Find whether ind_id is supported by local device or not */
-            int local_index = bta_ag_find_hf_ind_by_id(p_scb->local_hf_indicators,
-                                      BTA_AG_MAX_NUM_LOCAL_HF_IND, p_result->data.ind.id);
-            if (local_index == -1)
-            {
-                APPL_TRACE_WARNING("%s Invalid HF Indicator ID %d", __func__,
-                    p_result->data.ind.id);
-                return;
-            }
+       case BTA_AG_BIND_RES:
+           bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+           break;
 
-            /* Find whether ind_id is supported by peer device or not */
-            int peer_index = bta_ag_find_hf_ind_by_id(p_scb->peer_hf_indicators,
-                                      BTA_AG_MAX_NUM_PEER_HF_IND, p_result->data.ind.id);
-            if (peer_index == -1)
-            {
-                APPL_TRACE_WARNING("%s Invalid HF Indicator ID %d", __func__,
-                    p_result->data.ind.id);
-                return;
-            } else {
-                /* If the current state is different from the one upper layer request
-                   change current state and send out the result */
-                if (p_scb->local_hf_indicators[local_index].is_enable != p_result->data.ind.on_demand)
-                {
-                    char buffer[BTA_AG_AT_MAX_LEN] = {0};
-                    char *p = buffer;
-
-                    p_scb->local_hf_indicators[local_index].is_enable = p_result->data.ind.on_demand;
-                    p += utl_itoa(p_result->data.ind.id, p);
-                    *p++ = ',';
-                    p += utl_itoa(p_scb->local_hf_indicators[local_index].is_enable, p);
-
-                    bta_ag_send_result(p_scb, p_result->result, buffer, 0);
-                } else {
-                    APPL_TRACE_DEBUG("%s HF Indicator %d already %s", p_result->data.ind.id,
-                        (p_result->data.ind.on_demand == true) ? "Enabled" : "Disabled");
-                }
-            }
+       default:
             break;
         }
-
-        default:
-            break;
     }
-}
+
 
 /*******************************************************************************
 **
@@ -1918,7 +2068,7 @@
 
     /* send +BCS */
     APPL_TRACE_DEBUG("send +BCS codec is %d", codec_uuid);
-    bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_BCS, NULL, codec_uuid);
+    bta_ag_send_result(p_scb, BTA_AG_RES_BCS, NULL, codec_uuid);
 
 }
 #endif
@@ -1937,14 +2087,41 @@
 {
     UNUSED(p_data);
 
+    if ((p_scb->conn_service == BTA_AG_HFP) &&
+         p_scb->callsetup_ind != BTA_AG_CALLSETUP_INCOMING)
+    {
+        APPL_TRACE_DEBUG("don't send the ring since there is no MT call setup");
+        return;
+    }
+
+#if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
+    tBTA_AG_MULTI_RESULT_CB m_res_cb;
+
+    if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled && p_scb->clip[0] != 0)
+    {
+        memset(&m_res_cb, NULL, sizeof(tBTA_AG_MULTI_RESULT_CB));
+
+        m_res_cb.num_result = 2;
+        AT_SET_RES_CB(m_res_cb.res_cb[0], BTA_AG_RES_RING, NULL, 0)
+        AT_SET_RES_CB(m_res_cb.res_cb[1], BTA_AG_RES_CLIP, p_scb->clip, 0)
+
+        bta_ag_send_multi_result(p_scb, &m_res_cb);
+    }
+    else
+    {
+        /* send RING ONLY */
+        bta_ag_send_result(p_scb, BTA_AG_RES_RING, NULL, 0);
+    }
+#else
     /* send RING */
-    bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_RING, NULL, 0);
+    bta_ag_send_result(p_scb, BTA_AG_RES_RING, NULL, 0);
 
     /* if HFP and clip enabled and clip data send CLIP */
     if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled && p_scb->clip[0] != 0)
     {
-        bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_CLIP, p_scb->clip, 0);
+        bta_ag_send_result(p_scb, BTA_AG_RES_CLIP, p_scb->clip, 0);
     }
+#endif
 
     bta_sys_start_timer(p_scb->ring_timer, BTA_AG_RING_TIMEOUT_MS,
                         BTA_AG_RING_TIMEOUT_EVT, bta_ag_scb_to_idx(p_scb));
diff --git a/bta/ag/bta_ag_int.h b/bta/ag/bta_ag_int.h
index eac98c2..fa32e67 100644
--- a/bta/ag/bta_ag_int.h
+++ b/bta/ag/bta_ag_int.h
@@ -28,10 +28,30 @@
 #include "bta_api.h"
 #include "bta_ag_api.h"
 #include "bta_ag_at.h"
+#include "osi/include/log.h"
+
+/* Send RING & CLIP in one AT cmd */
+#ifndef BTA_AG_MULTI_RESULT_INCLUDED
+#define BTA_AG_MULTI_RESULT_INCLUDED      FALSE
+#endif
+
+/* Replace : in VGS and VGM for HSP */
+#ifndef BTA_HSP_RESULT_REPLACE_COLON
+#define BTA_HSP_RESULT_REPLACE_COLON      TRUE
+#endif
 
 /*****************************************************************************
 **  Constants
 *****************************************************************************/
+#define HFP_VERSION_1_1         0x0101
+#define HFP_VERSION_1_5         0x0105
+#define HFP_VERSION_1_6         0x0106
+#define HFP_VERSION_1_7         0x0107
+
+
+#define HSP_VERSION_1_0         0x0100
+#define HSP_VERSION_1_2         0x0102
+
 /* Number of SCBs (AG service instances that can be registered) */
 #ifndef BTA_AG_NUM_SCB
 #define BTA_AG_NUM_SCB          2
@@ -45,10 +65,6 @@
 /* RFCOMM MTU SIZE */
 #define BTA_AG_MTU              256
 
-/* Max number of peer and local HF indicators */
-#define BTA_AG_MAX_NUM_PEER_HF_IND     20
-#define BTA_AG_MAX_NUM_LOCAL_HF_IND    4
-
 /* Internal profile indexes */
 #define BTA_AG_HSP              0       /* index for HSP */
 #define BTA_AG_HFP              1       /* index for HFP */
@@ -64,7 +80,7 @@
                                       BTA_AG_FEAT_VTAG | BTA_AG_FEAT_REJECT  | \
                                       BTA_AG_FEAT_ECS  | BTA_AG_FEAT_ECC     | \
                                       BTA_AG_FEAT_EXTERR | BTA_AG_FEAT_CODEC | \
-                                      BTA_AG_FEAT_HF_IND | BTA_AG_FEAT_ESCO  | \
+                                      BTA_AG_FEAT_HFIND| BTA_AG_FEAT_S4| \
                                       BTA_AG_FEAT_VOIP)
 
 #define BTA_AG_SDP_FEAT_SPEC         (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR    | \
@@ -285,11 +301,8 @@
     BOOLEAN             codec_fallback; /* If sco nego fails for mSBC, fallback to CVSD */
     tBTA_AG_SCO_MSBC_SETTINGS codec_msbc_settings; /* settings to be used for the impending eSCO */
 #endif
+    BOOLEAN             slc_pend_open;  /* SLC is pending open */
 
-    tBTA_AG_HF_IND      peer_hf_indicators[BTA_AG_MAX_NUM_PEER_HF_IND];   /* Peer supported
-                                                                      HF indicators */
-    tBTA_AG_HF_IND      local_hf_indicators[BTA_AG_MAX_NUM_LOCAL_HF_IND]; /* Local supported
-                                                                      HF indicators */
 } tBTA_AG_SCB;
 
 /* type for sco data */
@@ -334,7 +347,6 @@
 
 /* config struct */
 extern tBTA_AG_CFG *p_bta_ag_cfg;
-extern tBTA_AG_HF_IND bta_ag_local_hf_ind_cfg[];
 
 /*****************************************************************************
 **  Function prototypes
diff --git a/bta/ag/bta_ag_main.c b/bta/ag/bta_ag_main.c
index 3abd1ef..182985c 100644
--- a/bta/ag/bta_ag_main.c
+++ b/bta/ag/bta_ag_main.c
@@ -783,7 +783,7 @@
     {
         if ((p_scb = bta_ag_scb_by_idx(p_data->hdr.layer_specific)) != NULL)
         {
-            APPL_TRACE_DEBUG("bta_ag_api_result: p_scb 0x%08x ", p_scb);
+            APPL_TRACE_IMP("bta_ag_api_result: p_scb 0x%08x ", p_scb);
             bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data);
         }
     }
@@ -815,23 +815,21 @@
     tBTA_AG_ST_TBL      state_table;
     UINT8               action;
     int                 i;
-
-#if BTA_AG_DEBUG == TRUE
     UINT16  in_event = event;
     UINT8   in_state = p_scb->state;
 
-    /* Ignore displaying of AT results when not connected (Ignored in state machine) */
     if (in_event != BTA_AG_API_RESULT_EVT || p_scb->state == BTA_AG_OPEN_ST)
     {
-        APPL_TRACE_EVENT("AG evt (hdl 0x%04x): State %d (%s), Event 0x%04x (%s)",
+        #if BTA_AG_DEBUG == TRUE
+            APPL_TRACE_IMP("AG evt (hdl 0x%04x): State %d (%s), Event 0x%04x (%s)",
                            bta_ag_scb_to_idx(p_scb),
                            p_scb->state, bta_ag_state_str(p_scb->state),
                            event, bta_ag_evt_str(event, p_data->api_result.result));
+        #else
+           APPL_TRACE_IMP("AG evt (hdl 0x%04x): State %d, Event 0x%04x",
+                           bta_ag_scb_to_idx(p_scb), p_scb->state, event);
+        #endif
     }
-#else
-    APPL_TRACE_EVENT("AG evt (hdl 0x%04x): State %d, Event 0x%04x",
-                      bta_ag_scb_to_idx(p_scb), p_scb->state, event);
-#endif
 
     event &= 0x00FF;
     if (event >= (BTA_AG_MAX_EVT & 0x00FF))
@@ -840,6 +838,9 @@
         return;
     }
 
+    /* If SLC time out, dump the logs */
+    if (event == BTA_AG_SVC_TIMEOUT_EVT)
+        GENERATE_VND_LOGS();
     /* look up the state table for the current state */
     state_table = bta_ag_st_tbl[p_scb->state];
 
@@ -849,7 +850,10 @@
     /* execute action functions */
     for (i = 0; i < BTA_AG_ACTIONS; i++)
     {
-        if ((action = state_table[event][i]) != BTA_AG_IGNORE)
+        /* Fix for below klockwork issue.
+         * Klockwork issue: Possible attempt to access element 33..255 of array 'bta_ag_action'
+         * whose size is 32 */
+        if (((action = state_table[event][i]) < BTA_AG_IGNORE) && (action >= 0))
         {
             (*bta_ag_action[action])(p_scb, p_data);
         }
@@ -858,15 +862,18 @@
             break;
         }
     }
-#if BTA_AG_DEBUG == TRUE
     if (p_scb->state != in_state)
     {
-        APPL_TRACE_EVENT("BTA AG State Change: [%s] -> [%s] after Event [%s]",
+        #if BTA_AG_DEBUG == TRUE
+            APPL_TRACE_IMP("BTA AG State Change: [%s] -> [%s] after Event [%s]",
                       bta_ag_state_str(in_state),
                       bta_ag_state_str(p_scb->state),
                       bta_ag_evt_str(in_event, p_data->api_result.result));
+        #else
+            APPL_TRACE_IMP("BTA AG State Change: [%d] -> [%d]",
+                              in_state, p_scb->state);
+        #endif
     }
-#endif
 }
 
 /*******************************************************************************
@@ -910,7 +917,7 @@
         default:
             if ((p_scb = bta_ag_scb_by_idx(p_msg->layer_specific)) != NULL)
             {
-                APPL_TRACE_DEBUG("bta_ag_hdl_event: p_scb 0x%08x ", p_scb);
+                APPL_TRACE_IMP("bta_ag_hdl_event: p_scb 0x%08x ", p_scb);
                 bta_ag_sm_execute(p_scb, p_msg->event, (tBTA_AG_DATA *) p_msg);
             }
             break;
@@ -958,6 +965,7 @@
         case BTA_AG_CALL_CANCEL_RES:    return ("AT Result  BTA_AG_CALL_CANCEL_RES");
         case BTA_AG_END_CALL_RES:       return ("AT Result  BTA_AG_END_CALL_RES");
         case BTA_AG_UNAT_RES:           return ("AT Result  BTA_AG_UNAT_RES");
+        case BTA_AG_BIND_RES:           return ("AT Result  BTA_AG_BIND_RES");
         default:                        return ("Unknown AG Result");
         }
     case BTA_AG_API_SETCODEC_EVT:
diff --git a/bta/ag/bta_ag_rfc.c b/bta/ag/bta_ag_rfc.c
index d3f2705..b0bf6b9 100644
--- a/bta/ag/bta_ag_rfc.c
+++ b/bta/ag/bta_ag_rfc.c
@@ -287,11 +287,12 @@
         {
             BTM_SetSecurityLevel(FALSE, "", bta_ag_sec_id[i], p_scb->serv_sec_mask,
                 BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, bta_ag_cb.profile[i].scn);
-
+            /* Fix for below klockwork issue
+             * Array 'bta_ag_mgmt_cback_tbl' size is 3.
+             * Possible attempt to access element -1,3..USHRT_MAX-1 of array 'bta_ag_mgmt_cback_tbl'. */
             bta_ag_port_status =  RFCOMM_CreateConnection(bta_ag_uuid[i], bta_ag_cb.profile[i].scn,
                 TRUE, BTA_AG_MTU, (UINT8 *) bd_addr_any, &(p_scb->serv_handle[i]),
-                bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]);
-
+                bta_ag_mgmt_cback_tbl[(UINT16)(bta_ag_scb_to_idx(p_scb) - 1)]);
             if( bta_ag_port_status  == PORT_SUCCESS )
             {
                 bta_ag_setup_port(p_scb, p_scb->serv_handle[i]);
@@ -369,13 +370,15 @@
 {
     BTM_SetSecurityLevel(TRUE, "", bta_ag_sec_id[p_scb->conn_service],
         p_scb->cli_sec_mask, BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, p_scb->peer_scn);
-
+    /* Fix for below klockwork issue
+     * Array 'bta_ag_mgmt_cback_tbl' size is 3.
+     * Possible attempt to access element -1,3..USHRT_MAX-1 of array 'bta_ag_mgmt_cback_tbl' */
     if (RFCOMM_CreateConnection(bta_ag_uuid[p_scb->conn_service], p_scb->peer_scn,
             FALSE, BTA_AG_MTU, p_scb->peer_addr, &(p_scb->conn_handle),
-            bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]) == PORT_SUCCESS)
+            bta_ag_mgmt_cback_tbl[(UINT16)(bta_ag_scb_to_idx(p_scb) - 1)]) == PORT_SUCCESS)
     {
         bta_ag_setup_port(p_scb, p_scb->conn_handle);
-        APPL_TRACE_DEBUG("bta_ag_rfc_do_open : conn_handle = %d", p_scb->conn_handle);
+        APPL_TRACE_IMP("bta_ag_rfc_do_open : conn_handle = %d", p_scb->conn_handle);
     }
     /* RFCOMM create connection failed; send ourselves RFCOMM close event */
     else
diff --git a/bta/ag/bta_ag_sco.c b/bta/ag/bta_ag_sco.c
index 89e6f6c..8bbbe24 100644
--- a/bta/ag/bta_ag_sco.c
+++ b/bta/ag/bta_ag_sco.c
@@ -33,6 +33,8 @@
 #include "btm_api.h"
 #include "bt_common.h"
 #include "utl.h"
+#include "device/include/interop.h"
+//#include "osi/include/log.h"
 
 #ifndef BTA_AG_SCO_DEBUG
 #define BTA_AG_SCO_DEBUG FALSE
@@ -40,10 +42,11 @@
 
 /* Codec negotiation timeout */
 #ifndef BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS
-#define BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS (3 * 1000)          /* 3 seconds */
+#define BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS (5 * 1000)          /* 5 seconds */
 #endif
 
 extern fixed_queue_t *btu_bta_alarm_queue;
+extern void bta_dm_pm_set_sniff_policy_toggle(BD_ADDR peer_addr, BOOLEAN bDisable);
 
 #if BTA_AG_SCO_DEBUG == TRUE
 static char *bta_ag_sco_evt_str(UINT8 event);
@@ -73,19 +76,36 @@
 };
 
 #if (BTM_WBS_INCLUDED == TRUE )
-#define BTA_AG_NUM_CODECS   3
-#define BTA_AG_ESCO_SETTING_IDX_CVSD    0   /* eSCO setting for CVSD */
-#define BTA_AG_ESCO_SETTING_IDX_T1      1   /* eSCO setting for mSBC T1 */
-#define BTA_AG_ESCO_SETTING_IDX_T2      2   /* eSCO setting for mSBC T2 */
+#define BTA_AG_NUM_CODECS   4
+#define BTA_AG_ESCO_SETTING_IDX_CVSD_S4    0   /* eSCO S4 setting for CVSD */
+#define BTA_AG_ESCO_SETTING_IDX_CVSD_S3    1   /* eSCO S3 setting for CVSD */
+#define BTA_AG_ESCO_SETTING_IDX_T1         2   /* eSCO setting for mSBC T1 */
+#define BTA_AG_ESCO_SETTING_IDX_T2         3   /* eSCO setting for mSBC T2 */
 
 static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] =
 {
-    /* CVSD */
+    /* CVSD S4 */
     {
         BTM_64KBITS_RATE,                   /* TX Bandwidth (64 kbits/sec)              */
         BTM_64KBITS_RATE,                   /* RX Bandwidth (64 kbits/sec)              */
         0x000c,                             /* 12 ms (HS/HF can use EV3, 2-EV3, 3-EV3)  */
         BTM_VOICE_SETTING_CVSD,             /* Inp Linear, Air CVSD, 2s Comp, 16bit     */
+       (BTM_SCO_PKT_TYPES_MASK_HV1      +  /* Packet Types                             */
+        BTM_SCO_PKT_TYPES_MASK_HV2      +
+        BTM_SCO_PKT_TYPES_MASK_HV3      +
+        BTM_SCO_PKT_TYPES_MASK_EV3      +
+        BTM_SCO_PKT_TYPES_MASK_EV4      +
+        BTM_SCO_PKT_TYPES_MASK_EV5      +
+        BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
+        BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
+        BTM_ESCO_RETRANS_QUALITY       /* Retransmission effort                      */
+    },
+    /* CVSD S3 */
+    {
+        BTM_64KBITS_RATE,                   /* TX Bandwidth (64 kbits/sec)              */
+        BTM_64KBITS_RATE,                   /* RX Bandwidth (64 kbits/sec)              */
+        0x000a,                             /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3)  */
+        BTM_VOICE_SETTING_CVSD,             /* Inp Linear, Air CVSD, 2s Comp, 16bit     */
        (BTM_SCO_PKT_TYPES_MASK_HV1      +   /* Packet Types                             */
         BTM_SCO_PKT_TYPES_MASK_HV2      +
         BTM_SCO_PKT_TYPES_MASK_HV3      +
@@ -94,7 +114,7 @@
         BTM_SCO_PKT_TYPES_MASK_EV5      +
         BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
         BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
-        BTM_ESCO_RETRANS_QUALITY            /* Retransmission effort                    */
+        BTM_ESCO_RETRANS_POWER       /* Retransmission effort                      */
     },
     /* mSBC  T1 */
     {
@@ -124,21 +144,40 @@
 };
 #else
 /* WBS not included, CVSD by default */
-static const tBTM_ESCO_PARAMS bta_ag_esco_params =
+static const tBTM_ESCO_PARAMS bta_ag_esco_params[] =
 {
-    BTM_64KBITS_RATE,                   /* TX Bandwidth (64 kbits/sec)              */
-    BTM_64KBITS_RATE,                   /* RX Bandwidth (64 kbits/sec)              */
-    0x000a,                             /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3)  */
-    0x0060,                             /* Inp Linear, Air CVSD, 2s Comp, 16bit     */
-    (BTM_SCO_PKT_TYPES_MASK_HV1      +  /* Packet Types                             */
-     BTM_SCO_PKT_TYPES_MASK_HV2      +
-     BTM_SCO_PKT_TYPES_MASK_HV3      +
-     BTM_SCO_PKT_TYPES_MASK_EV3      +
-     BTM_SCO_PKT_TYPES_MASK_EV4      +
-     BTM_SCO_PKT_TYPES_MASK_EV5      +
-     BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
-     BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
-     BTM_ESCO_RETRANS_POWER       /* Retransmission effort                      */
+    /* CVSD S4 */
+    {
+        BTM_64KBITS_RATE,                   /* TX Bandwidth (64 kbits/sec)              */
+        BTM_64KBITS_RATE,                   /* RX Bandwidth (64 kbits/sec)              */
+        0x000c,                             /* 12 ms (HS/HF can use EV3, 2-EV3, 3-EV3)  */
+        BTM_VOICE_SETTING_CVSD,             /* Inp Linear, Air CVSD, 2s Comp, 16bit     */
+       (BTM_SCO_PKT_TYPES_MASK_HV1      +  /* Packet Types                             */
+        BTM_SCO_PKT_TYPES_MASK_HV2      +
+        BTM_SCO_PKT_TYPES_MASK_HV3      +
+        BTM_SCO_PKT_TYPES_MASK_EV3      +
+        BTM_SCO_PKT_TYPES_MASK_EV4      +
+        BTM_SCO_PKT_TYPES_MASK_EV5      +
+        BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
+        BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
+        BTM_ESCO_RETRANS_QUALITY       /* Retransmission effort                      */
+    },
+    /* CVSD S3 */
+    {
+        BTM_64KBITS_RATE,                   /* TX Bandwidth (64 kbits/sec)              */
+        BTM_64KBITS_RATE,                   /* RX Bandwidth (64 kbits/sec)              */
+        0x000a,                             /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3)  */
+        0x0060,                             /* Inp Linear, Air CVSD, 2s Comp, 16bit     */
+        (BTM_SCO_PKT_TYPES_MASK_HV1      +  /* Packet Types                             */
+         BTM_SCO_PKT_TYPES_MASK_HV2      +
+         BTM_SCO_PKT_TYPES_MASK_HV3      +
+         BTM_SCO_PKT_TYPES_MASK_EV3      +
+         BTM_SCO_PKT_TYPES_MASK_EV4      +
+         BTM_SCO_PKT_TYPES_MASK_EV5      +
+         BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
+         BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
+         BTM_ESCO_RETRANS_POWER       /* Retransmission effort                      */
+    }
 };
 #endif
 
@@ -199,7 +238,7 @@
 {
     UINT16  handle = 0;
 
-    APPL_TRACE_DEBUG ("bta_ag_sco_disc_cback(): sco_idx: 0x%x  p_cur_scb: 0x%08x  sco.state: %d", sco_idx, bta_ag_cb.sco.p_curr_scb, bta_ag_cb.sco.state);
+    APPL_TRACE_IMP("bta_ag_sco_disc_cback(): sco_idx: 0x%x  p_cur_scb: 0x%08x  sco.state: %d", sco_idx, bta_ag_cb.sco.p_curr_scb, bta_ag_cb.sco.state);
 
     APPL_TRACE_DEBUG ("bta_ag_sco_disc_cback(): scb[0] addr: 0x%08x  in_use: %u  sco_idx: 0x%x  sco state: %u",
                        &bta_ag_cb.scb[0], bta_ag_cb.scb[0].in_use, bta_ag_cb.scb[0].sco_idx, bta_ag_cb.scb[0].state);
@@ -231,13 +270,17 @@
         /* Restore settings */
         if(bta_ag_cb.sco.p_curr_scb->inuse_codec == BTA_AG_CODEC_MSBC)
         {
+#if (BLUETOOTH_QTI_SW == FALSE) /* This change is not needed.*/
             /* set_sco_codec(BTM_SCO_CODEC_NONE); we should get a close */
             BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD);
+#endif
 
-            /* If SCO open was initiated by AG and failed for mSBC, then attempt
-            mSBC with T1 settings i.e. 'Safe Settings'. If this fails, then switch to CVSD */
+            /* If SCO open was initiated by AG and failed for mSBC,then switch to CVSD
+               as our BT SOC has already tried the T1 safe setting for SCO failure before
+               updating to the BT HOST.*/
             if (bta_ag_sco_is_opening (bta_ag_cb.sco.p_curr_scb))
             {
+#if (BLUETOOTH_QTI_SW == FALSE) /* This change is not needed.*/
                 if (bta_ag_cb.sco.p_curr_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2)
                 {
                      APPL_TRACE_DEBUG("Fallback to mSBC T1 settings");
@@ -248,6 +291,12 @@
                     APPL_TRACE_DEBUG("Fallback to CVSD settings");
                     bta_ag_cb.sco.p_curr_scb->codec_fallback = TRUE;
                 }
+#else
+                {
+                    APPL_TRACE_DEBUG("Fallback to CVSD settings");
+                    bta_ag_cb.sco.p_curr_scb->codec_fallback = TRUE;
+                }
+#endif
             }
         }
 
@@ -258,6 +307,10 @@
         p_buf->event = BTA_AG_SCO_CLOSE_EVT;
         p_buf->layer_specific = handle;
         bta_sys_sendmsg(p_buf);
+        if (interop_match_addr(INTEROP_DISABLE_SNIFF_POLICY_DURING_SCO,
+                        (const bt_bdaddr_t *)&bta_ag_cb.sco.p_curr_scb->peer_addr)) {
+            bta_dm_pm_set_sniff_policy_toggle(bta_ag_cb.sco.p_curr_scb->peer_addr, false);
+        }
     } else {
         /* no match found */
         APPL_TRACE_DEBUG("no scb for ag_sco_disc_cback");
@@ -314,7 +367,7 @@
         {
             status = BTM_RemoveSco(p_scb->sco_idx);
 
-            APPL_TRACE_DEBUG("ag remove sco: inx 0x%04x, status:0x%x", p_scb->sco_idx, status);
+            APPL_TRACE_IMP("ag remove sco: inx 0x%04x, status:0x%x", p_scb->sco_idx, status);
 
             if (status == BTM_CMD_STARTED)
             {
@@ -361,7 +414,7 @@
             /* If no other SCO active, allow this one */
             if (!bta_ag_cb.sco.p_curr_scb)
             {
-                APPL_TRACE_EVENT("bta_ag_esco_connreq_cback: Accept Conn Request (sco_inx 0x%04x)", sco_inx);
+                APPL_TRACE_IMP("bta_ag_esco_connreq_cback: Accept Conn Request (sco_inx 0x%04x)", sco_inx);
                 bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt);
 
                 bta_ag_cb.sco.state = BTA_AG_SCO_OPENING_ST;
@@ -370,7 +423,7 @@
             }
             else    /* Begin a transfer: Close current SCO before responding */
             {
-                APPL_TRACE_DEBUG("bta_ag_esco_connreq_cback: Begin XFER");
+                APPL_TRACE_IMP("bta_ag_esco_connreq_cback: Begin XFER");
                 bta_ag_cb.sco.p_xfer_scb = p_scb;
                 bta_ag_cb.sco.conn_data = p_data->conn_evt;
                 bta_ag_cb.sco.state = BTA_AG_SCO_OPEN_XFER_ST;
@@ -438,9 +491,9 @@
     tBTM_STATUS       status;
     UINT8            *p_bd_addr = NULL;
     tBTM_ESCO_PARAMS params;
+    int codec_index = (p_scb->peer_features & BTA_AG_PEER_FEAT_S4) ? 0 : 1;
 #if (BTM_WBS_INCLUDED == TRUE )
     tBTA_AG_PEER_CODEC  esco_codec = BTM_SCO_CODEC_CVSD;
-    int codec_index = 0;
 #endif
 #if (BTM_SCO_HCI_INCLUDED == TRUE )
     tBTM_SCO_ROUTE_TYPE sco_route;
@@ -487,7 +540,7 @@
     params = bta_ag_esco_params[codec_index];
 #else
     /* When WBS is not included, use CVSD by default */
-    params = bta_ag_esco_params;
+    params = bta_ag_esco_params[codec_index];
 #endif
 
     if(bta_ag_cb.sco.param_updated) /* If we do not use the default parameters */
@@ -551,6 +604,7 @@
         bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
 
 #if (BTM_WBS_INCLUDED == TRUE )
+#if (BLUETOOTH_QTI_SW == FALSE) /* These changes are not needed*/
         /* Allow any platform specific pre-SCO set up to take place */
         bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP,
                 esco_codec);
@@ -561,6 +615,7 @@
             BTM_WriteVoiceSettings (BTM_VOICE_SETTING_TRANS);
         else
             BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD);
+#endif
         /* save the current codec because sco_codec can be updated while SCO is open. */
         p_scb->inuse_codec = esco_codec;
 #else
@@ -606,7 +661,7 @@
         }
     }
 
-    APPL_TRACE_API("ag create sco: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
+    APPL_TRACE_IMP("ag create sco: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
                       is_orig, p_scb->sco_idx, status, params.packet_types);
 }
 
@@ -644,6 +699,10 @@
 {
     tBTA_AG_SCB *p_scb = (tBTA_AG_SCB *)data;
 
+    APPL_TRACE_IMP("codec negotiation timedout, aborting SCO/eSCO creation");
+
+    GENERATE_VND_LOGS();
+
     /* Announce that codec negotiation failed. */
     bta_ag_sco_codec_nego(p_scb, FALSE);
 
@@ -710,15 +769,15 @@
 #if (BTM_SCO_HCI_INCLUDED == TRUE )
     BT_HDR  *p_buf;
 #endif
-#if BTA_AG_SCO_DEBUG == TRUE
     UINT8   in_state = p_sco->state;
 
-    APPL_TRACE_EVENT("BTA ag sco evt (hdl 0x%04x): State %d (%s), Event %d (%s)",
+#if BTA_AG_SCO_DEBUG == TRUE
+    APPL_TRACE_IMP("BTA ag sco evt (hdl 0x%04x): State %d (%s), Event %d (%s)",
                         p_scb->sco_idx,
                         p_sco->state, bta_ag_sco_state_str(p_sco->state),
                         event, bta_ag_sco_evt_str(event));
 #else
-    APPL_TRACE_EVENT("BTA ag sco evt (hdl 0x%04x): State %d, Event %d",
+    APPL_TRACE_IMP("BTA ag sco evt (hdl 0x%04x): State %d, Event %d",
                       p_scb->sco_idx, p_sco->state, event);
 #endif
 
@@ -773,9 +832,17 @@
                     bta_ag_remove_sco(p_scb, FALSE);
 
 #if (BTM_WBS_INCLUDED == TRUE )
-                    /* start codec negotiation */
-                    p_sco->state = BTA_AG_SCO_CODEC_ST;
-                    p_cn_scb = p_scb;
+                    if (p_scb->peer_codecs != BTA_AG_CODEC_NONE)
+                    {
+                        /* start codec negotiation */
+                        p_sco->state = BTA_AG_SCO_CODEC_ST;
+                        p_cn_scb = p_scb;
+                    }
+                    else
+                    {
+                        bta_ag_create_sco(p_scb, TRUE);
+                        p_sco->state = BTA_AG_SCO_OPENING_ST;
+                    }
 #else
                     /* create sco connection to peer */
                     bta_ag_create_sco(p_scb, TRUE);
@@ -899,15 +966,19 @@
                     break;
 
                 case BTA_AG_SCO_SHUTDOWN_E:
-                    /* If not opening scb, just close it */
-                    if (p_scb != p_sco->p_curr_scb)
-                    {
-                        /* remove listening connection */
-                        bta_ag_remove_sco(p_scb, FALSE);
-                    }
-                    else
-                        p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+                    /* remove listening connection */
+                    bta_ag_remove_sco(p_scb, FALSE);
 
+                    if (p_scb == p_sco->p_curr_scb)
+                    {
+                        p_sco->p_curr_scb = NULL;
+                    }
+
+                    /* If last SCO instance then finish shutting down */
+                    if (!bta_ag_other_scb_open(p_scb))
+                    {
+                        p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
+                    }
                     break;
 
                 case BTA_AG_SCO_CONN_OPEN_E:
@@ -941,15 +1012,19 @@
                     break;
 
                 case BTA_AG_SCO_SHUTDOWN_E:
-                    /* If not opening scb, just close it */
-                    if (p_scb != p_sco->p_curr_scb)
-                    {
-                        /* remove listening connection */
-                        bta_ag_remove_sco(p_scb, FALSE);
-                    }
-                    else
-                        p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+                    /* remove listening connection */
+                    bta_ag_remove_sco(p_scb, FALSE);
 
+                    if (p_scb == p_sco->p_curr_scb)
+                    {
+                        p_sco->p_curr_scb = NULL;
+                    }
+
+                    /* If last SCO instance then finish shutting down */
+                    if (!bta_ag_other_scb_open(p_scb))
+                    {
+                        p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
+                    }
                     break;
 
                 case BTA_AG_SCO_CONN_OPEN_E:
@@ -1120,9 +1195,17 @@
 
                 case BTA_AG_SCO_CONN_CLOSE_E:
 #if (BTM_WBS_INCLUDED == TRUE )
-                    /* start codec negotiation */
-                    p_sco->state = BTA_AG_SCO_CODEC_ST;
-                    p_cn_scb = p_scb;
+                    if (p_scb->peer_codecs != BTA_AG_CODEC_NONE)
+                    {
+                        /* start codec negotiation */
+                        p_sco->state = BTA_AG_SCO_CODEC_ST;
+                        p_cn_scb = p_scb;
+                    }
+                    else
+                    {
+                        bta_ag_create_sco(p_scb, TRUE);
+                        p_sco->state = BTA_AG_SCO_OPENING_ST;
+                    }
 #else
                     /* open sco connection */
                     bta_ag_create_sco(p_scb, TRUE);
@@ -1175,10 +1258,19 @@
                     bta_ag_remove_sco(p_sco->p_xfer_scb, FALSE);
 
 #if (BTM_WBS_INCLUDED == TRUE )
-                    /* start codec negotiation */
-                    p_sco->state = BTA_AG_SCO_CODEC_ST;
-                    p_cn_scb = p_sco->p_xfer_scb;
-                    p_sco->p_xfer_scb = NULL;
+                    if (p_scb->peer_codecs != BTA_AG_CODEC_NONE)
+                    {
+                        /* start codec negotiation */
+                        p_sco->state = BTA_AG_SCO_CODEC_ST;
+                        p_cn_scb = p_sco->p_xfer_scb;
+                        p_sco->p_xfer_scb = NULL;
+                    }
+                    else
+                    {
+                        bta_ag_create_sco(p_sco->p_xfer_scb, TRUE);
+                        p_sco->p_xfer_scb = NULL;
+                        p_sco->state = BTA_AG_SCO_OPENING_ST;
+                    }
 #else
                     /* create sco connection to peer */
                     bta_ag_create_sco(p_sco->p_xfer_scb, TRUE);
@@ -1261,15 +1353,19 @@
         default:
             break;
     }
-#if BTA_AG_SCO_DEBUG == TRUE
+
     if (p_sco->state != in_state)
     {
-        APPL_TRACE_EVENT("BTA AG SCO State Change: [%s] -> [%s] after Event [%s]",
-                      bta_ag_sco_state_str(in_state),
-                      bta_ag_sco_state_str(p_sco->state),
-                      bta_ag_sco_evt_str(event));
+        #if BTA_AG_SCO_DEBUG == TRUE
+            APPL_TRACE_IMP("BTA AG SCO State Change: [%s] -> [%s] after Event [%s]",
+                          bta_ag_sco_state_str(in_state),
+                          bta_ag_sco_state_str(p_sco->state),
+                          bta_ag_sco_evt_str(event));
+        #else
+            APPL_TRACE_IMP("BTA AG SCO State Change: [%d] -> [%d] after Event [%d]",
+                                in_state, p_sco->state, event);
+        #endif
     }
-#endif
 
 #if (BTM_WBS_INCLUDED == TRUE )
     if (p_cn_scb)
@@ -1384,7 +1480,7 @@
     if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX)
 #endif
     {
-        APPL_TRACE_DEBUG("bta_ag_sco_close: sco_inx = %d", p_scb->sco_idx);
+        APPL_TRACE_IMP("bta_ag_sco_close: sco_inx = %d", p_scb->sco_idx);
         bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
     }
 }
@@ -1575,9 +1671,19 @@
         {
             resp.rx_bw = BTM_64KBITS_RATE;
             resp.tx_bw = BTM_64KBITS_RATE;
-            resp.max_latency = 12;
+            if ((p_scb->peer_features & BTA_AG_PEER_FEAT_S4) &&
+                    (p_scb->features & BTA_AG_PEER_FEAT_S4))
+            {
+                APPL_TRACE_WARNING("bta_ag_sco_conn_rsp with S4 link settings");
+                resp.max_latency = 12;
+                resp.retrans_effort = BTM_ESCO_RETRANS_QUALITY;
+            }
+            else
+            {
+                resp.max_latency = 10;
+                resp.retrans_effort = BTM_ESCO_RETRANS_POWER;
+            }
             resp.voice_contfmt = 0x60;
-            resp.retrans_effort = BTM_ESCO_RETRANS_QUALITY;
 
             if (p_data->link_type == BTM_LINK_TYPE_SCO)
             {
diff --git a/bta/ag/bta_ag_sdp.c b/bta/ag/bta_ag_sdp.c
index aa43c02..b25dd9c 100644
--- a/bta/ag/bta_ag_sdp.c
+++ b/bta/ag/bta_ag_sdp.c
@@ -23,6 +23,9 @@
  *
  ******************************************************************************/
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
 #include <string.h>
 #include "bta_api.h"
 #include "bta_sys.h"
@@ -32,6 +35,8 @@
 #include "btm_api.h"
 #include "bt_common.h"
 #include "utl.h"
+#include "bt_utils.h"
+#include "device/include/interop_config.h"
 
 /* Number of protocol elements in protocol element list. */
 #define BTA_AG_NUM_PROTO_ELEMS      2
@@ -159,7 +164,7 @@
     if (service_uuid == UUID_SERVCLASS_AG_HANDSFREE)
     {
         profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
-        version = BTA_HFP_VERSION;
+        version = HFP_VERSION_1_6;
     }
     else
     {
@@ -322,7 +327,8 @@
     }
     else
     {
-        return result;
+        uuid = UUID_SERVCLASS_HEADSET_HS;
+        p_scb->peer_version = 0x0100;   /* Default version */
     }
 
     /* loop through all records we found */
@@ -371,6 +377,16 @@
                 if (p_scb->peer_features == 0)
                     p_scb->peer_features = p_attr->attr_value.v.u16;
             }
+
+            /* Remote supports 1.7, store it in the file */
+            if (p_scb->peer_version == HFP_VERSION_1_7)
+            {
+                bt_bdaddr_t remote_bdaddr;
+                bdcpy(remote_bdaddr.address, p_scb->peer_addr);
+                interop_database_add_addr(INTEROP_HFP_1_7_BLACKLIST,
+                                (bt_bdaddr_t *)&remote_bdaddr, 3);
+            }
+
         }
         else    /* HSP */
         {
@@ -445,10 +461,21 @@
             num_uuid = 2;
         }
     }
-    /* HSP acceptor; no discovery */
+    /* HSP acceptor; get features */
     else
     {
-        return;
+       attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+       attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
+       attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
+       attr_list[3] = ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL;
+       num_attr = 4;
+
+       uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HEADSET;        /* Legacy from HSP v1.0 */
+       if (p_scb->hsp_version >= HSP_VERSION_1_2)
+       {
+           uuid_list[1].uu.uuid16 = UUID_SERVCLASS_HEADSET_HS;
+           num_uuid = 2;
+       }
     }
 
     /* allocate buffer for sdp database */
@@ -462,8 +489,11 @@
     if(db_inited)
     {
         /*Service discovery not initiated */
+        /*Fix for below Klockwork issue
+         *Array 'bta_ag_sdp_cback_tbl' size is 3
+         *Possible attempt to access element -1,3..USHRT_MAX-1 of array 'bta_ag_sdp_cback_tbl' */
         db_inited = SDP_ServiceSearchAttributeRequest(p_scb->peer_addr, p_scb->p_disc_db,
-                                      bta_ag_sdp_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]);
+                                      bta_ag_sdp_cback_tbl[(UINT16)(bta_ag_scb_to_idx(p_scb) - 1)]);
     }
 
     if(!db_inited)
diff --git a/bta/av/bta_av_aac.c b/bta/av/bta_av_aac.c
new file mode 100644
index 0000000..d358a6c
--- /dev/null
+++ b/bta/av/bta_av_aac.c
@@ -0,0 +1,82 @@
+/******************************************************************************
+ *
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *   met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of The Linux Foundation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+  ******************************************************************************/
+
+#include "a2d_api.h"
+#include "a2d_aac.h"
+#include "bta_av_aac.h"
+#include "utl.h"
+
+/*******************************************************************************
+**
+** Function         bta_av_aac_cfg_in_cap
+**
+** Description      Checks if AAC codec config is allowed for given caps.
+**                  codec config bits are also checked for sanity
+**
+** Returns          0 if ok, nonzero if error.
+**
+*******************************************************************************/
+UINT8 bta_av_aac_cfg_in_cap(UINT8 *p_cfg, tA2D_AAC_CIE *p_cap)
+{
+    UINT8           status = 0;
+    tA2D_AAC_CIE    cfg_cie;
+
+    /* parse configuration */
+    if ((status = A2D_ParsAacInfo(&cfg_cie, p_cfg, FALSE)) != 0)
+    {
+        APPL_TRACE_DEBUG("bta_av_aac_cfg_in_cap can't parse  %d", status);
+        return status;
+    }
+
+    /* object type */
+    if ((cfg_cie.object_type & p_cap->object_type) == 0)
+    {
+        status = A2D_NS_OBJ_TYPE;
+    }
+    /* frequency */
+    else if ((cfg_cie.samp_freq & p_cap->samp_freq) == 0)
+    {
+        status = A2D_NS_SAMP_FREQ;
+    }
+    /* channels */
+    else if ((cfg_cie.channels & p_cap->channels) == 0)
+    {
+        status = A2D_NS_CHANNEL;
+    }
+    /* bitrate */
+    else if ((cfg_cie.bit_rate & p_cap->bit_rate || cfg_cie.bit_rate < p_cap->bit_rate ) == 0)
+    {
+        status = A2D_NS_BIT_RATE;
+    }
+    APPL_TRACE_DEBUG("bta_av_aac_cfg_in_cap return %d", status);
+    return status;
+}
+
diff --git a/bta/av/bta_av_aact.c b/bta/av/bta_av_aact.c
index 1e73fa6..92188d5 100644
--- a/bta/av/bta_av_aact.c
+++ b/bta/av/bta_av_aact.c
@@ -1,4 +1,9 @@
 /******************************************************************************
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a contribution.
+ ******************************************************************************/
+/******************************************************************************
  *
  *  Copyright (C) 2004-2012 Broadcom Corporation
  *
@@ -33,6 +38,8 @@
 #include "avdt_api.h"
 #include "bta_av_int.h"
 #include "bt_utils.h"
+#include "a2d_aptx.h"
+#include "a2d_aptx_hd.h"
 #include "l2cdefs.h"
 #include "l2c_api.h"
 #include "osi/include/properties.h"
@@ -43,6 +50,7 @@
 #include "bta_ar_api.h"
 #endif
 
+extern BOOLEAN is_sniff_disabled;
 /*****************************************************************************
 **  Constants
 *****************************************************************************/
@@ -62,14 +70,20 @@
 #define BTA_AV_RECONFIG_RETRY       6
 #endif
 
+static const size_t SBC_MIN_BITPOOL_OFFSET = 5;
+static const size_t SBC_MAX_BITPOOL_OFFSET = 6;
+
+#ifdef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
+static const size_t SBC_MAX_BITPOOL = 51;
+#else
+static const size_t SBC_MAX_BITPOOL = 53;
+#endif
+
 /* ACL quota we are letting FW use for A2DP Offload Tx. */
 #define BTA_AV_A2DP_OFFLOAD_XMIT_QUOTA      4
 
 static void bta_av_st_rc_timer(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
 
-static const size_t SBC_MAX_BITPOOL_OFFSET = 6;
-static const size_t SBC_MAX_BITPOOL = 53;
-
 /* state machine states */
 enum
 {
@@ -94,7 +108,9 @@
     bta_av_co_audio_start,
     bta_av_co_audio_stop,
     bta_av_co_audio_src_data_path,
-    bta_av_co_audio_delay
+    bta_av_co_audio_delay,
+    bta_av_co_audio_is_offload_supported,
+    bta_av_co_audio_is_codec_supported
 };
 
 /* ssm action functions for audio stream */
@@ -252,10 +268,34 @@
 ***********************************************/
 static UINT8 bta_av_get_scb_handle(tBTA_AV_SCB *p_scb, UINT8 local_sep)
 {
-    for (int i = 0; i < BTA_AV_MAX_SEPS; i++) {
-        if ((p_scb->seps[i].tsep == local_sep) &&
-            (p_scb->seps[i].codec_type == p_scb->codec_type))
-            return (p_scb->seps[i].av_handle);
+    UINT8 xx =0;
+    for (xx = 0; xx<BTA_AV_MAX_SEPS; xx++)
+    {
+        if ((p_scb->seps[xx].tsep == local_sep) &&
+            (p_scb->seps[xx].codec_type == p_scb->codec_type))
+        {
+            if (p_scb->seps[xx].codec_type != A2D_NON_A2DP_MEDIA_CT)
+                return (p_scb->seps[xx].av_handle);
+            else {
+                UINT8 losc = p_scb->cfg.codec_info[0];
+                if (losc == A2D_APTX_CODEC_LEN)
+                {
+                    tA2D_APTX_CIE aptx_config;
+                    if (A2D_ParsAptxInfo(&aptx_config, p_scb->cfg.codec_info, FALSE) == A2D_SUCCESS)
+                        if ((aptx_config.codecId == p_scb->seps[xx].codecId) &&
+                            (aptx_config.vendorId == p_scb->seps[xx].vendorId))
+                           return (p_scb->seps[xx].av_handle);
+                } else if (losc == A2D_APTX_HD_CODEC_LEN)
+                {
+                    tA2D_APTX_HD_CIE aptx_config;
+                    if (A2D_ParsAptx_hdInfo(&aptx_config, p_scb->cfg.codec_info, FALSE) == A2D_SUCCESS)
+                        if ((aptx_config.codecId == p_scb->seps[xx].codecId) &&
+                            (aptx_config.vendorId == p_scb->seps[xx].vendorId))
+                           return (p_scb->seps[xx].av_handle);
+                } else
+                    APPL_TRACE_DEBUG("%s: Invalid aptX Losc", __func__)
+            }
+        }
     }
     APPL_TRACE_DEBUG(" bta_av_get_scb_handle appropiate sep_type not found")
     return 0; /* return invalid handle */
@@ -272,9 +312,11 @@
 ***********************************************/
 static UINT8 bta_av_get_scb_sep_type(tBTA_AV_SCB *p_scb, UINT8 tavdt_handle)
 {
-    for (int i = 0; i < BTA_AV_MAX_SEPS; i++) {
-        if (p_scb->seps[i].av_handle == tavdt_handle)
-            return (p_scb->seps[i].tsep);
+    UINT8 xx =0;
+    for (xx = 0; xx<BTA_AV_MAX_SEPS; xx++)
+    {
+        if (p_scb->seps[xx].av_handle == tavdt_handle)
+            return (p_scb->seps[xx].tsep);
     }
     APPL_TRACE_DEBUG(" bta_av_get_scb_sep_type appropiate handle not found")
     return 3; /* return invalid sep type */
@@ -396,7 +438,7 @@
             /* we got a stream; get its capabilities */
             if (p_scb->p_cap == NULL)
                 p_scb->p_cap = (tAVDT_CFG *)osi_malloc(sizeof(tAVDT_CFG));
-            if (p_scb->avdt_version >= AVDT_VERSION_SYNC)
+            if ((p_scb->avdt_version >= AVDT_VERSION_SYNC) && (a2d_get_avdt_sdp_ver() >= AVDT_VERSION_SYNC) )
             {
                 p_req = AVDT_GetAllCapReq;
             }
@@ -404,11 +446,15 @@
             {
                 p_req = AVDT_GetCapReq;
             }
-            (*p_req)(p_scb->peer_addr,
+            if ((*p_req)(p_scb->peer_addr,
                            p_scb->sep_info[i].seid,
-                           p_scb->p_cap, bta_av_dt_cback[p_scb->hdi]);
-            sent_cmd = TRUE;
-            break;
+                           p_scb->p_cap, bta_av_dt_cback[p_scb->hdi]) == AVDT_SUCCESS)
+            {
+                sent_cmd = TRUE;
+                break;
+            }
+            else
+                APPL_TRACE_ERROR("bta_av_next_getcap command could not be sent because of resource constraint");
         }
     }
 
@@ -435,6 +481,8 @@
 {
     UINT16              sec_len = 0;
     tBTA_AV_SCB         *p_scb = bta_av_cb.p_scb[index];
+    int                 xx;
+    APPL_TRACE_VERBOSE("bta_av_proc_stream_evt on the index : %d", index);
 
     if (p_data)
     {
@@ -487,7 +535,11 @@
              * If we already have a signalling connection with the bd_addr and the streaming
              * SST is at INIT state, change it to INCOMING state to handle the signalling
              * from the 2nd SEP.                                                                */
-            if ((bta_av_find_lcb(bd_addr, BTA_AV_LCB_FIND) != NULL) && (bta_av_is_scb_init(p_scb)))
+            /* Fix for below klockwork issue
+             * Pointer 'bd_addr' checked for NULL at line 465 may be passed to function and
+             * may be dereferenced there by passing argument 1 to function 'bta_av_find_lcb' at line 500
+             * added another null check for below condition to get rid of kw error */
+            if (bd_addr != NULL && (bta_av_find_lcb(bd_addr, BTA_AV_LCB_FIND) != NULL) && (bta_av_is_scb_init(p_scb)))
             {
                 bta_av_set_scb_sst_incoming (p_scb);
 
@@ -495,11 +547,14 @@
                  * Later when we receive AVDT_CONFIG_IND_EVT, we use a new p_scb and set its state to
                  * incoming which we do it above.
                  * We also have to set the old p_scb state to init to be used later             */
-                for (int i = 0; i < BTA_AV_NUM_STRS; i++) {
-                    if ((bta_av_cb.p_scb[i]) && (i != index)) {
-                        if (bta_av_cb.p_scb[i]->state == BTA_AV_INCOMING_SST) {
-                            bta_av_cb.p_scb[i]->state = BTA_AV_INIT_SST;
-                            bta_av_cb.p_scb[i]->coll_mask = 0;
+                for (xx = 0; xx < BTA_AV_NUM_STRS; xx++)
+                {
+                    if ((bta_av_cb.p_scb[xx]) && (xx != index))
+                    {
+                        if (bta_av_cb.p_scb[xx]->state == BTA_AV_INCOMING_SST)
+                        {
+                            bta_av_cb.p_scb[xx]->state = BTA_AV_INIT_SST;
+                            bta_av_cb.p_scb[xx]->coll_mask = 0;
                             break;
                         }
                     }
@@ -556,11 +611,14 @@
 /* coverity[var_deref_model] */
 /* false-positive: bta_av_conn_cback only processes AVDT_CONNECT_IND_EVT and AVDT_DISCONNECT_IND_EVT event
  *                 these 2 events always have associated p_data */
-    if (p_data)
+/* Fix for below klockwork issue
+ * Pointer 'bd_addr' checked for NULL at line 465 may be passed to function and may be dereferenced there
+ * by passing argument 2 to function 'bta_av_conn_cback'. */
+    if (p_data && bd_addr)
     {
         bta_av_conn_cback(handle, bd_addr, event, p_data);
     }
-    else
+    else if (!p_data)
     {
         APPL_TRACE_ERROR("%s: p_data is null", __func__);
     }
@@ -727,6 +785,9 @@
     p_msg->hdr.layer_specific = bta_av_cb.handle;
 
     bta_sys_sendmsg(p_msg);
+    if (!found)
+        APPL_TRACE_ERROR ("bta_av_a2d_sdp_cback, SDP record not found");
+    bta_sys_conn_close(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
 }
 
 /*******************************************************************************
@@ -740,16 +801,56 @@
 *******************************************************************************/
 static void bta_av_adjust_seps_idx(tBTA_AV_SCB *p_scb, UINT8 avdt_handle)
 {
+    int xx;
     APPL_TRACE_DEBUG("bta_av_adjust_seps_idx codec_type: %d", p_scb->codec_type);
-    for (int i = 0; i < BTA_AV_MAX_SEPS; i++) {
+    for(xx=0; xx<BTA_AV_MAX_SEPS; xx++)
+    {
         APPL_TRACE_DEBUG("av_handle: %d codec_type: %d",
-            p_scb->seps[i].av_handle, p_scb->seps[i].codec_type);
-        if((p_scb->seps[i].av_handle && p_scb->codec_type == p_scb->seps[i].codec_type)
-            && (p_scb->seps[i].av_handle == avdt_handle))
+            p_scb->seps[xx].av_handle, p_scb->seps[xx].codec_type);
+        if((p_scb->seps[xx].av_handle && p_scb->codec_type == p_scb->seps[xx].codec_type)
+            && (p_scb->seps[xx].av_handle == avdt_handle))
         {
-            p_scb->sep_idx = i;
-            p_scb->avdt_handle = p_scb->seps[i].av_handle;
-            break;
+            if (p_scb->seps[xx].codec_type != A2D_NON_A2DP_MEDIA_CT)
+            {
+                p_scb->sep_idx      = xx;
+                p_scb->avdt_handle  = p_scb->seps[xx].av_handle;
+                break;
+            }
+            else {
+                UINT8 losc = p_scb->cfg.codec_info[0];
+                if (losc == A2D_APTX_CODEC_LEN)
+                {
+                    tA2D_APTX_CIE aptx_config;
+                    if (A2D_ParsAptxInfo(&aptx_config, p_scb->cfg.codec_info, FALSE) == A2D_SUCCESS) {
+                        APPL_TRACE_DEBUG("%s vendorId: %x codecId: %x", __func__, p_scb->seps[xx].vendorId, p_scb->seps[xx].codecId);
+                        if ((aptx_config.codecId == p_scb->seps[xx].codecId) &&
+                            (aptx_config.vendorId == p_scb->seps[xx].vendorId)) {
+                            APPL_TRACE_DEBUG("%s p_scb->sep_idx: %d", __func__, p_scb->sep_idx);
+                            p_scb->sep_idx = xx;
+                            p_scb->avdt_handle = p_scb->seps[xx].av_handle;
+                            APPL_TRACE_DEBUG("%s p_scb->sep_idx: %d", __func__, p_scb->sep_idx);
+                            APPL_TRACE_DEBUG("%s p_scb->avdt_handle: %d", __func__, p_scb->avdt_handle);
+                            break;
+                        }
+                    }
+                } else if (losc == A2D_APTX_HD_CODEC_LEN)
+                {
+                    tA2D_APTX_HD_CIE aptx_config;
+                    if (A2D_ParsAptx_hdInfo(&aptx_config, p_scb->cfg.codec_info, FALSE) == A2D_SUCCESS) {
+                        APPL_TRACE_DEBUG("%s vendorId: %x codecId: %x", __func__, p_scb->seps[xx].vendorId, p_scb->seps[xx].codecId);
+                        if ((aptx_config.codecId == p_scb->seps[xx].codecId) &&
+                            (aptx_config.vendorId == p_scb->seps[xx].vendorId)) {
+                            APPL_TRACE_DEBUG("%s p_scb->sep_idx: %d", __func__, p_scb->sep_idx);
+                            p_scb->sep_idx = xx;
+                            p_scb->avdt_handle = p_scb->seps[xx].av_handle;
+                            APPL_TRACE_DEBUG("%s p_scb->sep_idx: %d", __func__, p_scb->sep_idx);
+                            APPL_TRACE_DEBUG("%s p_scb->avdt_handle: %d", __func__, p_scb->avdt_handle);
+                            break;
+                        }
+                    }
+                } else
+                    APPL_TRACE_DEBUG("%s: Invalid aptX Losc", __func__)
+            }
         }
     }
 }
@@ -824,11 +925,32 @@
     BOOLEAN         initiator = FALSE;
     tBTA_AV_START   start;
     tBTA_AV_OPEN    av_open;
+    tBTA_AV_ROLE_CHANGED role_changed;
+
+    UINT8 cur_role = BTM_ROLE_UNDEFINED;
 
     APPL_TRACE_DEBUG("bta_av_role_res q_tag:%d, wait:x%x, role:x%x", p_scb->q_tag, p_scb->wait, p_scb->role);
     if (p_scb->role & BTA_AV_ROLE_START_INT)
         initiator = TRUE;
 
+    /* Multicast: update BTIF about role switch
+     * If role switch succeeded, we need to update multicast state
+     * from BTIF.
+     */
+    if (p_data->role_res.hci_status == HCI_SUCCESS)
+    {
+        APPL_TRACE_DEBUG("bta_av_role_res: Master update upper layer");
+
+        bdcpy(role_changed.bd_addr, p_scb->peer_addr);
+        role_changed.hndl = p_scb->hndl;
+
+        if (BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS)
+        {
+            role_changed.new_role = cur_role;
+        }
+        (*bta_av_cb.p_cback)(BTA_AV_ROLE_CHANGED_EVT, (tBTA_AV *)&role_changed);
+    }
+
     if (p_scb->q_tag == BTA_AV_Q_TAG_START)
     {
         if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_STARTED)
@@ -837,7 +959,7 @@
             if (p_data->role_res.hci_status != HCI_SUCCESS)
             {
                 p_scb->role &= ~BTA_AV_ROLE_START_INT;
-                bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+                bta_sys_idle(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
                 /* start failed because of role switch. */
                 start.chnl   = p_scb->chnl;
                 start.status = BTA_AV_FAIL_ROLE;
@@ -866,6 +988,11 @@
                 bdcpy(av_open.bd_addr, p_scb->peer_addr);
                 av_open.chnl   = p_scb->chnl;
                 av_open.hndl   = p_scb->hndl;
+                // update Master/Slave Role for open event
+                if (BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS)
+                {
+                    av_open.role = cur_role;
+                }
                 start.status = BTA_AV_FAIL_ROLE;
                 if(p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC )
                     av_open.sep = AVDT_TSEP_SNK;
@@ -996,7 +1123,7 @@
     p_scb->sec_mask = p_data->api_open.sec_mask;
     p_scb->use_rc = p_data->api_open.use_rc;
 
-    bta_sys_app_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+    bta_sys_conn_open(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
 
     if (p_scb->skip_sdp == TRUE)
     {
@@ -1010,30 +1137,32 @@
         bta_av_a2d_sdp_cback(TRUE, &a2d_ser);
         return;
     }
+    else
+    {
+        /* only one A2D find service is active at a time */
+        bta_av_cb.handle = p_scb->hndl;
 
-    /* only one A2D find service is active at a time */
-    bta_av_cb.handle = p_scb->hndl;
+        /* set up parameters */
+        db_params.db_len = BTA_AV_DISC_BUF_SIZE;
+        db_params.num_attr = 3;
+        db_params.p_attrs = attr_list;
+        p_scb->uuid_int = p_data->api_open.uuid;
+        p_scb->sdp_discovery_started = TRUE;
+        if (p_scb->uuid_int == UUID_SERVCLASS_AUDIO_SINK)
+            sdp_uuid = UUID_SERVCLASS_AUDIO_SOURCE;
+        else if (p_scb->uuid_int == UUID_SERVCLASS_AUDIO_SOURCE)
+            sdp_uuid = UUID_SERVCLASS_AUDIO_SINK;
 
-    /* set up parameters */
-    db_params.db_len = BTA_AV_DISC_BUF_SIZE;
-    db_params.num_attr = 3;
-    db_params.p_attrs = attr_list;
-    p_scb->uuid_int = p_data->api_open.uuid;
-    p_scb->sdp_discovery_started = TRUE;
-    if (p_scb->uuid_int == UUID_SERVCLASS_AUDIO_SINK)
-        sdp_uuid = UUID_SERVCLASS_AUDIO_SOURCE;
-    else if (p_scb->uuid_int == UUID_SERVCLASS_AUDIO_SOURCE)
-        sdp_uuid = UUID_SERVCLASS_AUDIO_SINK;
-
-    APPL_TRACE_DEBUG("%s: uuid_int 0x%x, Doing SDP For 0x%x", __func__,
+        APPL_TRACE_DEBUG("%s: uuid_int 0x%x, Doing SDP For 0x%x", __func__,
                     p_scb->uuid_int, sdp_uuid);
-    if (A2D_FindService(sdp_uuid, p_scb->peer_addr, &db_params,
+        if (A2D_FindService(sdp_uuid, p_scb->peer_addr, &db_params,
                     bta_av_a2d_sdp_cback) == A2D_SUCCESS)
-        return;
+            return;
 
-    /* when the code reaches here, either the DB is NULL
-     * or A2D_FindService is not successful */
-    bta_av_a2d_sdp_cback(FALSE, NULL);
+        /* when the code reaches here, either the DB is NULL
+         * or A2D_FindService is not successful */
+        bta_av_a2d_sdp_cback(FALSE, NULL);
+    }
 }
 
 /*******************************************************************************
@@ -1048,7 +1177,8 @@
 void bta_av_cleanup(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 {
     tBTA_AV_CONN_CHG msg;
-    UINT8 role = BTA_AV_ROLE_AD_INT;
+    int             xx;
+    UINT8           role = BTA_AV_ROLE_AD_INT;
     UNUSED(p_data);
 
     APPL_TRACE_DEBUG("bta_av_cleanup");
@@ -1064,6 +1194,7 @@
     /* if de-registering shut everything down */
     msg.hdr.layer_specific  = p_scb->hndl;
     p_scb->started  = FALSE;
+    p_scb->suspend_local_sent = FALSE;
     p_scb->cong = FALSE;
     p_scb->role = role;
     p_scb->cur_psc_mask = 0;
@@ -1078,15 +1209,18 @@
         (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, (tBTA_AV *)&status);
     }
     p_scb->offload_start_pending = FALSE;
+    p_scb->skip_sdp = FALSE;
+    p_scb->coll_mask = 0;
 
     p_scb->skip_sdp = FALSE;
     if (p_scb->deregistring)
     {
         /* remove stream */
-        for (int i = 0; i < BTA_AV_MAX_SEPS; i++) {
-            if (p_scb->seps[i].av_handle)
-                AVDT_RemoveStream(p_scb->seps[i].av_handle);
-            p_scb->seps[i].av_handle = 0;
+        for(xx=0; xx<BTA_AV_MAX_SEPS; xx++)
+        {
+            if(p_scb->seps[xx].av_handle)
+                AVDT_RemoveStream(p_scb->seps[xx].av_handle);
+            p_scb->seps[xx].av_handle = 0;
         }
 
         bta_av_dereg_comp((tBTA_AV_DATA *) &msg);
@@ -1140,8 +1274,17 @@
     p_scb->codec_type = p_evt_cfg->codec_info[BTA_AV_CODEC_TYPE_IDX];
     bta_av_save_addr(p_scb, p_data->str_msg.bd_addr);
 
-    /* Clear collision mask */
-    p_scb->coll_mask = 0;
+    if (p_scb->coll_mask & BTA_AV_COLL_API_CALLED)
+    {
+        APPL_TRACE_DEBUG(" bta_av_config_ind ReSetting collision mask  ");
+        /* Clear collision mask */
+        p_scb->coll_mask = 0;
+    }
+    else
+    {
+        APPL_TRACE_WARNING(" bta_av_config_ind config_ind called before Open");
+        p_scb->coll_mask |= BTA_AV_COLL_SETCONFIG_IND;
+    }
     alarm_cancel(bta_av_cb.accept_signalling_timer);
 
     /* if no codec parameters in configuration, fail */
@@ -1325,22 +1468,13 @@
             p_scb->avdt_version = AVDT_VERSION_SYNC;
 
 
-        if (p_scb->codec_type == BTA_AV_CODEC_SBC || num > 1)
-        {
-            /* if SBC is used by the SNK as INT, discover req is not sent in bta_av_config_ind.
-                       * call disc_res now */
-           /* this is called in A2DP SRC path only, In case of SINK we don't need it  */
-            if (local_sep == AVDT_TSEP_SRC)
-                p_scb->p_cos->disc_res(p_scb->hndl, num, num, 0, p_scb->peer_addr,
-                                                      UUID_SERVCLASS_AUDIO_SOURCE);
-        }
-        else
-        {
-            /* we do not know the peer device and it is using non-SBC codec
-             * we need to know all the SEPs on SNK */
-            bta_av_discover_req(p_scb, NULL);
-            return;
-        }
+        /* For any codec used by the SNK as INT, discover req is not sent in bta_av_config_ind.
+         * This is done since we saw an IOT issue with APTX codec. Thus, we now take same
+         * path for all codecs as for SBC. call disc_res now */
+        /* this is called in A2DP SRC path only, In case of SINK we don't need it  */
+        if (local_sep == AVDT_TSEP_SRC)
+            p_scb->p_cos->disc_res(p_scb->hndl, num, num, 0, p_scb->peer_addr,
+                                                  UUID_SERVCLASS_AUDIO_SOURCE);
 
         for (i = 1; i < num; i++)
         {
@@ -1358,6 +1492,8 @@
             /* Make sure UUID has been initialized... */
             if (p_scb->uuid_int == 0)
                 p_scb->uuid_int = p_scb->open_api.uuid;
+            if (p_scb->uuid_int == 0)
+                p_scb->uuid_int = UUID_SERVCLASS_AUDIO_SOURCE;
             bta_av_next_getcap(p_scb, p_data);
         }
     }
@@ -1378,6 +1514,7 @@
     tBTA_AV_OPEN    open;
     UINT8 *p;
     UINT16 mtu;
+    UINT8 cur_role;
 
     msg.hdr.layer_specific = p_scb->hndl;
     msg.is_up = TRUE;
@@ -1387,7 +1524,7 @@
     /* set the congestion flag, so AV would not send media packets by accident */
     p_scb->cong = TRUE;
     p_scb->offload_start_pending = FALSE;
-
+    p_scb->suspend_local_sent = FALSE;
 
     p_scb->stream_mtu = p_data->str_msg.msg.open_ind.peer_mtu - AVDT_MEDIA_HDR_SIZE;
     mtu = bta_av_chk_mtu(p_scb, p_scb->stream_mtu);
@@ -1396,17 +1533,17 @@
     if(mtu == 0 || mtu > p_scb->stream_mtu)
         mtu = p_scb->stream_mtu;
 
-    /* Set the media channel as medium priority */
-    L2CA_SetTxPriority(p_scb->l2c_cid, L2CAP_CHNL_PRIORITY_MEDIUM);
+    /* Set the media channel as high priority */
+    L2CA_SetTxPriority(p_scb->l2c_cid, L2CAP_CHNL_PRIORITY_HIGH);
     L2CA_SetChnlFlushability (p_scb->l2c_cid, TRUE);
 
-    bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+    bta_sys_conn_open(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
     memset(&p_scb->q_info, 0, sizeof(tBTA_AV_Q_INFO));
 
     p_scb->l2c_bufs = 0;
     p_scb->p_cos->open(p_scb->hndl,
         p_scb->codec_type, p_scb->cfg.codec_info, mtu);
-
+    bta_av_cb.codec_type = p_scb->codec_type;
     {
         /* TODO check if other audio channel is open.
          * If yes, check if reconfig is needed
@@ -1423,6 +1560,14 @@
         open.status = BTA_AV_SUCCESS;
         open.starting = bta_av_chk_start(p_scb);
         open.edr    = 0;
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+        open.stream_chnl_id = AVDT_GetStreamingDestChannelId(p_scb->l2c_cid);
+#endif
+        // update Master/Slave Role for start
+        if (BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS)
+        {
+            open.role = cur_role;
+        }
         if( NULL != (p = BTM_ReadRemoteFeatures(p_scb->peer_addr)))
         {
             if(HCI_EDR_ACL_2MPS_SUPPORTED(p))
@@ -1454,6 +1599,23 @@
         AVDT_AbortReq(p_scb->avdt_handle);
     }
 }
+/*******************************************************************************
+**
+** Function         bta_av_get_codec_type
+**
+** Description      Returns the codec_type from the most recently used scb
+**
+** Returns          bta_av_cb.codec_type
+**
+*******************************************************************************/
+UINT8 bta_av_get_codec_type(tBTA_AV_HNDL hndl)
+{
+    APPL_TRACE_DEBUG("%s: hdl = %x", __func__, hndl);
+    tBTA_AV_SCB *p_scb = bta_av_hndl_to_scb(hndl);
+    bta_av_cb.codec_type = p_scb->codec_type;
+    APPL_TRACE_DEBUG("%s [bta_av_cb.codec_type] %x", __func__, bta_av_cb.codec_type);
+    return bta_av_cb.codec_type;
+}
 
 /*******************************************************************************
 **
@@ -1536,6 +1698,7 @@
 
     /* close stream */
     p_scb->started = FALSE;
+    p_scb->suspend_local_sent = FALSE;
 
     /* drop the buffers queued in L2CAP */
     L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
@@ -1560,6 +1723,7 @@
 *******************************************************************************/
 void bta_av_connect_req(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 {
+    UINT16 result;
     UNUSED(p_data);
 
     p_scb->sdp_discovery_started = FALSE;
@@ -1574,7 +1738,17 @@
         return;
     }
 
-    AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask, bta_av_dt_cback[p_scb->hdi]);
+    result = AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask, bta_av_dt_cback[p_scb->hdi]);
+    if(result != AVDT_SUCCESS)
+    {
+        /* AVDT connect failed because of resource issue
+         * trigger the SDP fail event to enable the cleanup
+         * and set the stream to proper state.
+         */
+        p_scb->open_status = BTA_AV_FAIL_RESOURCES;
+        APPL_TRACE_ERROR("bta_av_connect_req: AVDT_ConnectReq failed: %d", result);
+        bta_av_ssm_execute(p_scb, BTA_AV_SDP_DISC_FAIL_EVT, NULL);
+    }
 }
 
 /*******************************************************************************
@@ -1591,7 +1765,7 @@
     if (!p_scb->open_status)
         p_scb->open_status = BTA_AV_FAIL_SDP;
 
-    p_scb->sdp_discovery_started = FALSE;
+    p_scb->sdp_discovery_started = TRUE;
     bta_av_str_closed(p_scb, p_data);
 }
 
@@ -1805,6 +1979,7 @@
     tBTA_AV_SCB * p_opened_scb = NULL;
     UINT8 idx;
     tBTA_AV_OPEN    open;
+    UINT8 cur_role;
 
     APPL_TRACE_DEBUG("bta_av_open_failed");
     p_scb->open_status = BTA_AV_FAIL_STREAM;
@@ -1829,6 +2004,15 @@
         open.status = BTA_AV_FAIL_GET_CAP;
         open.starting = bta_av_chk_start(p_scb);
         open.edr    = 0;
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+        open.stream_chnl_id = 0;
+#endif
+        // update Master/Slave Role for open event
+        if (BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS)
+        {
+            open.role = cur_role;
+        }
+
         /* set the state back to initial state */
         bta_av_set_scb_sst_init(p_scb);
 
@@ -1924,6 +2108,15 @@
             cfg.codec_info[SBC_MAX_BITPOOL_OFFSET] = SBC_MAX_BITPOOL;
         }
 
+        if ((uuid_int == UUID_SERVCLASS_AUDIO_SOURCE) &&
+            (cfg.codec_info[SBC_MIN_BITPOOL_OFFSET] > cfg.codec_info[SBC_MAX_BITPOOL_OFFSET]))
+        {
+            APPL_TRACE_WARNING("%s min bitpool value received for SBC is more than DUT supported Max bitpool"
+                    "Clamping the max bitpool configuration further from %d to %d.", __func__,
+                    cfg.codec_info[SBC_MAX_BITPOOL_OFFSET], cfg.codec_info[SBC_MIN_BITPOOL_OFFSET]);
+            cfg.codec_info[SBC_MAX_BITPOOL_OFFSET] = cfg.codec_info[SBC_MIN_BITPOOL_OFFSET];
+        }
+
         /* open the stream */
         AVDT_OpenReq(p_scb->seps[p_scb->sep_idx].av_handle, p_scb->peer_addr,
                      p_scb->sep_info[p_scb->sep_info_idx].seid, &cfg);
@@ -1980,8 +2173,11 @@
     UNUSED(p_data);
 
     /* send avdtp discover request */
-
-    AVDT_DiscoverReq(p_scb->peer_addr, p_scb->sep_info, BTA_AV_NUM_SEPS, bta_av_dt_cback[p_scb->hdi]);
+    if (AVDT_DiscoverReq(p_scb->peer_addr, p_scb->sep_info, BTA_AV_NUM_SEPS, bta_av_dt_cback[p_scb->hdi]) != AVDT_SUCCESS)
+    {
+        APPL_TRACE_ERROR("bta_av_discover_req command could not be sent because of resource constraint");
+        bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, p_data);
+    }
 }
 
 /*******************************************************************************
@@ -2034,7 +2230,7 @@
     if ((p_scb->started == FALSE) && ((p_scb->role & BTA_AV_ROLE_START_INT) == 0))
     {
         p_scb->role |= BTA_AV_ROLE_START_INT;
-        bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+        bta_sys_busy(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
 
         AVDT_StartReq(&p_scb->avdt_handle, 1);
     }
@@ -2044,7 +2240,9 @@
         if ( p_scb->wait == 0 ) {
             if (p_scb->role & BTA_AV_ROLE_SUSPEND) {
                 notify_start_failed(p_scb);
-            } else {
+            }
+            else
+            {
                 bta_av_start_ok(p_scb, NULL);
             }
         }
@@ -2069,10 +2267,13 @@
     BT_HDR  *p_buf;
     UINT8 policy = HCI_ENABLE_SNIFF_MODE;
 
+    if (is_sniff_disabled == true)
+        policy = 0;
+
     APPL_TRACE_ERROR("bta_av_str_stopped:audio_open_cnt=%d, p_data %x",
             bta_av_cb.audio_open_cnt, p_data);
 
-    bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+    bta_sys_idle(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
     if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 || bta_av_cb.audio_open_cnt == 1)
         policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
     bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);
@@ -2114,16 +2315,18 @@
 
     if (p_data && p_data->api_stop.suspend)
     {
-        APPL_TRACE_DEBUG("suspending: %d, sup:%d", start, p_scb->suspend_sup);
-        if ((start)  && (p_scb->suspend_sup))
+        APPL_TRACE_DEBUG("suspending: %d, sup:%d, suspend_local_sent = %d",
+                           start, p_scb->suspend_sup,p_scb->suspend_local_sent);
+        if ((start)  && (p_scb->suspend_sup) && (!p_scb->suspend_local_sent))
         {
+            p_scb->suspend_local_sent = TRUE;
             sus_evt = FALSE;
             p_scb->l2c_bufs = 0;
             AVDT_SuspendReq(&p_scb->avdt_handle, 1);
         }
 
         /* send SUSPEND_EVT event only if not in reconfiguring state and sus_evt is TRUE*/
-        if ((sus_evt)&&(p_scb->state != BTA_AV_RCFG_SST))
+        if ((sus_evt) && ((p_scb->suspend_local_sent) || (p_scb->state != BTA_AV_RCFG_SST)))
         {
             suspend_rsp.status = BTA_AV_SUCCESS;
             suspend_rsp.initiator = TRUE;
@@ -2159,6 +2362,7 @@
 {
     tAVDT_CFG   *p_cfg;
     tBTA_AV_API_STOP    stop;
+    tBTA_AV_RECONFIG    evt;
     tBTA_AV_API_RCFG    *p_rcfg = &p_data->api_reconfig;
 
     APPL_TRACE_DEBUG("bta_av_reconfig r:%d, s:%d idx: %d (o:%d)",
@@ -2169,7 +2373,19 @@
     /* store the new configuration in control block */
     if (p_scb->p_cap == NULL)
         p_scb->p_cap = (tAVDT_CFG *)osi_malloc(sizeof(tAVDT_CFG));
-    p_cfg = p_scb->p_cap;
+    if((p_cfg = p_scb->p_cap) == NULL)
+    {
+        /* report failure */
+        evt.status = BTA_AV_FAIL_RESOURCES;
+        evt.chnl   = p_scb->chnl;
+        evt.hndl   = p_scb->hndl;
+        (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt);
+
+        /* this event is not possible in this state.
+         * use it to bring the SSM back to open state */
+        bta_av_ssm_execute(p_scb, BTA_AV_SDP_DISC_OK_EVT, NULL);
+        return;
+    }
 
     alarm_cancel(p_scb->avrc_ct_timer);
 
@@ -2334,7 +2550,9 @@
     UINT8           new_role = p_scb->role;
     BT_HDR          hdr;
     UINT8           policy = HCI_ENABLE_SNIFF_MODE;
-    UINT8           cur_role;
+    /* Fix for below klockwork issue
+     * 'cur_role' might be used uninitialized in this function */
+    UINT8           cur_role = BTM_ROLE_UNDEFINED;
 
     APPL_TRACE_DEBUG("bta_av_start_ok wait:x%x, role:x%x", p_scb->wait, p_scb->role);
 
@@ -2368,7 +2586,7 @@
         p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
         if (p_data->hdr.offset == BTA_AV_RS_FAIL)
         {
-            bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+            bta_sys_idle(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
             start.chnl   = p_scb->chnl;
             start.status = BTA_AV_FAIL_ROLE;
             start.hndl   = p_scb->hndl;
@@ -2407,9 +2625,9 @@
     }
 
     /* tell role manager to check M/S role */
-    bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+    bta_sys_conn_open(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
 
-    bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+    bta_sys_busy(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
 
     if(p_scb->media_type == AVDT_MEDIA_AUDIO)
     {
@@ -2435,7 +2653,24 @@
     }
     else if ((new_role & BTA_AV_ROLE_AD_ACP) && (new_role & BTA_AV_ROLE_SUSPEND_OPT))
     {
-        suspend = TRUE;
+
+        if (bta_av_is_multicast_enabled() == TRUE &&
+            (BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS)
+            && (cur_role == BTM_ROLE_MASTER))
+        {
+            /* If playing on other stream, dont suspend this. */
+            if (bta_av_chk_start(p_scb))
+            {
+                suspend = FALSE;
+                APPL_TRACE_DEBUG("cur_role: %d suspend: %d", cur_role, suspend);
+            }
+        }
+        else
+        {
+            suspend = TRUE;
+            APPL_TRACE_DEBUG("cur_role: %d suspend: %d", cur_role, suspend);
+
+        }
     }
 
     if (!suspend)
@@ -2476,6 +2711,11 @@
         start.chnl   = p_scb->chnl;
         start.status = BTA_AV_SUCCESS;
         start.hndl   = p_scb->hndl;
+        // update Master/Slave Role for start event
+        if (BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS)
+        {
+            start.role = cur_role;
+        }
         (*bta_av_cb.p_cback)(BTA_AV_START_EVT, (tBTA_AV *) &start);
 
         if(suspend)
@@ -2507,11 +2747,16 @@
 
     if(p_scb->started == FALSE && p_scb->co_started == FALSE)
     {
-        bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+        bta_sys_idle(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
         notify_start_failed(p_scb);
     }
 
-    bta_sys_set_policy(BTA_ID_AV, (HCI_ENABLE_SNIFF_MODE|HCI_ENABLE_MASTER_SLAVE_SWITCH), p_scb->peer_addr);
+    // if sniff is disabled in hf client, don't enable it again
+    if (is_sniff_disabled == true)
+        bta_sys_set_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_scb->peer_addr);
+    else
+        bta_sys_set_policy(BTA_ID_AV, (HCI_ENABLE_SNIFF_MODE|HCI_ENABLE_MASTER_SLAVE_SWITCH), p_scb->peer_addr);
+
     p_scb->sco_suspend = FALSE;
 }
 
@@ -2531,6 +2776,9 @@
     UINT16      mtu;
     UINT8 policy = HCI_ENABLE_SNIFF_MODE;
 
+    if (is_sniff_disabled == true)
+        policy = 0;
+
     if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 || bta_av_cb.audio_open_cnt == 1)
         policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
     bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);
@@ -2556,7 +2804,7 @@
         event = BTA_AV_OPEN_EVT;
         p_scb->open_status = BTA_AV_SUCCESS;
 
-        bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+        bta_sys_conn_close(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
         bta_av_cleanup(p_scb, p_data);
         (*bta_av_cb.p_cback)(event, &data);
     }
@@ -2577,7 +2825,7 @@
             data.close.hndl = p_scb->hndl;
             event = BTA_AV_CLOSE_EVT;
 
-            bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+            bta_sys_conn_close(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
             bta_av_cleanup(p_scb, p_data);
             (*bta_av_cb.p_cback)(event, &data);
         }
@@ -2615,9 +2863,12 @@
     tBTA_AV_SUSPEND suspend_rsp;
     UINT8           err_code = p_data->str_msg.msg.hdr.err_code;
     UINT8 policy = HCI_ENABLE_SNIFF_MODE;
+    p_scb->suspend_local_sent = FALSE;
+    if (is_sniff_disabled == true)
+        policy = 0;
 
-    APPL_TRACE_DEBUG ("bta_av_suspend_cfm:audio_open_cnt = %d, err_code = %d",
-        bta_av_cb.audio_open_cnt, err_code);
+    APPL_TRACE_DEBUG ("%s:audio_open_cnt = %d, err_code = %d, scb_started = %d",
+                      __func__,bta_av_cb.audio_open_cnt,err_code,p_scb->started);
 
     if (p_scb->started == FALSE)
     {
@@ -2656,9 +2907,10 @@
         p_scb->cong = FALSE;
     }
 
-    bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+    bta_sys_idle(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
     if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 || bta_av_cb.audio_open_cnt == 1)
         policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+
     bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);
 
     /* in case that we received suspend_ind, we may need to call co_stop here */
@@ -2835,7 +3087,7 @@
 {
     UINT8       err_code = p_data->str_msg.msg.hdr.err_code;
     tBTA_AV_RECONFIG    evt;
-
+    p_scb->suspend_local_sent = FALSE;
     p_scb->started = FALSE;
     p_scb->cong    = FALSE;
     if (err_code)
@@ -2890,7 +3142,7 @@
     */
     if (err_code)
     {
-        APPL_TRACE_ERROR("reconfig rejected, try close");
+        APPL_TRACE_ERROR("reconfig rejected, try close with error code = %d", err_code);
          /* Disable reconfiguration feature only with explicit rejection(not with timeout) */
         if (err_code != AVDT_ERR_TIMEOUT)
         {
@@ -2923,7 +3175,7 @@
 {
     UNUSED(p_data);
 
-	APPL_TRACE_DEBUG("bta_av_rcfg_open, num_disc_snks = %d", p_scb->num_disc_snks);
+    APPL_TRACE_DEBUG("%s: bta_av_rcfg_open, num_disc_snks = %d", __func__, p_scb->num_disc_snks);
 
     if (p_scb->num_disc_snks == 0)
     {
@@ -2940,7 +3192,7 @@
         /* we may choose to use a different SEP at reconfig.
          * adjust the sep_idx now */
         bta_av_adjust_seps_idx(p_scb, bta_av_get_scb_handle(p_scb, AVDT_TSEP_SRC));
-
+        bta_av_cb.codec_type = p_scb->codec_type;
         /* open the stream with the new config */
         p_scb->sep_info_idx = p_scb->rcfg_idx;
         AVDT_OpenReq(p_scb->avdt_handle, p_scb->peer_addr,
@@ -2983,7 +3235,9 @@
     BOOLEAN new_started = FALSE;
     UNUSED(p_data);
 
-    if ((p_scb->chnl == BTA_AV_CHNL_AUDIO) && (bta_av_cb.audio_open_cnt >= 2))
+    APPL_TRACE_DEBUG("%s\n", __func__);
+    if ((p_scb->chnl == BTA_AV_CHNL_AUDIO) && (bta_av_cb.audio_open_cnt >= 2) &&
+         bta_av_is_multicast_enabled())
     {
         /* more than one audio channel is connected */
         if (!(p_scb->role & BTA_AV_ROLE_SUSPEND_OPT))
@@ -3098,8 +3352,22 @@
 *******************************************************************************/
 void bta_av_open_at_inc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 {
+    if (!p_scb)
+    {
+        APPL_TRACE_WARNING("scb is NULL, bailing out!");
+        return;
+    }
+
     memcpy (&(p_scb->open_api), &(p_data->api_open), sizeof(tBTA_AV_API_OPEN));
 
+    if (p_scb->coll_mask & BTA_AV_COLL_SETCONFIG_IND)
+    {
+        APPL_TRACE_WARNING(" SetConfig is already called, timer stopped");
+        /* make mask 0, timer shld have already been closed in setconfig_ind */
+        p_scb->coll_mask = 0;
+        return;
+    }
+
     if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR)
     {
         p_scb->coll_mask |= BTA_AV_COLL_API_CALLED;
@@ -3111,6 +3379,7 @@
     {
         /* SNK did not start signalling, API was called N seconds timeout. */
         /* We need to switch to INIT state and start opening connection. */
+        APPL_TRACE_ERROR(" bta_av_open_at_inc ReSetting collision mask  ");
         p_scb->coll_mask = 0;
         bta_av_set_scb_sst_init(p_scb);
 
diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c
old mode 100644
new mode 100755
index 7154865..1a4148c
--- a/bta/av/bta_av_act.c
+++ b/bta/av/bta_av_act.c
@@ -29,6 +29,9 @@
 
 #if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE)
 
+
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "avdt_api.h"
@@ -37,10 +40,14 @@
 #include "l2c_api.h"
 #include "log/log.h"
 #include "osi/include/list.h"
+#include "bt_utils.h"
+#include <errno.h>
+
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
 #include "osi/include/properties.h"
 #include "utl.h"
+#include "device/include/interop.h"
 
 #if ( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
 #include "bta_ar_api.h"
@@ -60,9 +67,36 @@
 #define BTA_AV_ACCEPT_SIGNALLING_TIMEOUT_MS     (2 * 1000)      /* 2 seconds */
 #endif
 
+#ifndef AVRC_CONNECT_RETRY_DELAY_MS
+#define AVRC_CONNECT_RETRY_DELAY_MS 2000
+#endif
+
 extern fixed_queue_t *btu_bta_alarm_queue;
 
 static void bta_av_accept_signalling_timer_cback(void *data);
+struct blacklist_entry
+{
+    int ver;
+    char addr[3];
+};
+
+
+#ifndef AVRC_MIN_META_CMD_LEN
+#define AVRC_MIN_META_CMD_LEN 20
+#endif
+
+#define AVRC_L2CAP_MIN_CONN_FAILURE_CODE 2 /*same as L2CAP_CONN_NO_PSM*/
+
+/* state machine states */
+enum
+{
+    BTA_AV_INIT_SST,
+    BTA_AV_INCOMING_SST,
+    BTA_AV_OPENING_SST,
+    BTA_AV_OPEN_SST,
+    BTA_AV_RCFG_SST,
+    BTA_AV_CLOSING_SST
+};
 
 /*******************************************************************************
 **
@@ -216,13 +250,24 @@
 static void bta_av_rc_ctrl_cback(UINT8 handle, UINT8 event, UINT16 result, BD_ADDR peer_addr)
 {
     UINT16 msg_event = 0;
-    UNUSED(result);
 
 #if (defined(BTA_AV_MIN_DEBUG_TRACES) && BTA_AV_MIN_DEBUG_TRACES == TRUE)
     APPL_TRACE_EVENT("rc_ctrl handle: %d event=0x%x", handle, event);
 #else
-    APPL_TRACE_EVENT("bta_av_rc_ctrl_cback handle: %d event=0x%x", handle, event);
+    BTIF_TRACE_IMP("bta_av_rc_ctrl_cback handle: %d event=0x%x", handle, event);
 #endif
+    if (((event == AVRC_OPEN_IND_EVT) || (event == AVRC_CLOSE_IND_EVT))
+        && (result >= AVRC_L2CAP_MIN_CONN_FAILURE_CODE))
+    {
+        APPL_TRACE_WARNING("AVRCP connection encountered error=%x", result);
+        tBTA_AV_RC_COLLISSION_DETECTED *p_msg =
+            (tBTA_AV_RC_COLLISSION_DETECTED *)osi_malloc(sizeof(tBTA_AV_RC_COLLISSION_DETECTED));
+        p_msg->hdr.event = BTA_AV_RC_COLLISSION_DETECTED_EVT;
+        p_msg->handle = handle;
+        if (peer_addr)
+            bdcpy(p_msg->peer_addr, peer_addr);
+        bta_sys_sendmsg(p_msg);
+    }
     if (event == AVRC_OPEN_IND_EVT)
     {
         /* save handle of opened connection
@@ -260,7 +305,7 @@
     UINT8           *p_data_src = NULL;
     UINT16          data_len = 0;
 
-    APPL_TRACE_DEBUG("%s handle: %u opcode=0x%x", __func__, handle, opcode);
+    BTIF_TRACE_IMP("%s handle: %u opcode=0x%x", __func__, handle, opcode);
 
     /* Determine the size of the buffer we need */
     if (opcode == AVRC_OP_VENDOR && p_msg->vendor.p_vendor_data != NULL) {
@@ -269,8 +314,13 @@
     } else if (opcode == AVRC_OP_PASS_THRU && p_msg->pass.p_pass_data != NULL) {
         p_data_src = p_msg->pass.p_pass_data;
         data_len = (UINT16) p_msg->pass.pass_len;
+    } else if (opcode == AVRC_OP_BROWSE && p_msg->browse.p_browse_data != NULL) {
+        APPL_TRACE_EVENT("bta_av_rc_msg_cback Browse Data");
+        p_data_src  = p_msg->browse.p_browse_data;
+        data_len = (UINT16) p_msg->browse.browse_len;
     }
 
+
     /* Create a copy of the message */
     tBTA_AV_RC_MSG *p_buf =
         (tBTA_AV_RC_MSG *)osi_malloc(sizeof(tBTA_AV_RC_MSG) + data_len);
@@ -287,6 +337,8 @@
             p_buf->msg.vendor.p_vendor_data = p_data_dst;
         else if (opcode == AVRC_OP_PASS_THRU)
             p_buf->msg.pass.p_pass_data = p_data_dst;
+        else if (opcode == AVRC_OP_BROWSE)
+            p_buf->msg.browse.p_browse_data = p_data_dst;
     }
 
     bta_sys_sendmsg(p_buf);
@@ -306,13 +358,14 @@
     tAVRC_CONN_CB ccb;
     BD_ADDR_PTR   bda = (BD_ADDR_PTR)bd_addr_any;
     UINT8         status = BTA_AV_RC_ROLE_ACP;
-    tBTA_AV_SCB  *p_scb = p_cb->p_scb[shdl - 1];
+    tBTA_AV_SCB  *p_scb;
     int i;
     UINT8   rc_handle;
     tBTA_AV_RCB *p_rcb;
 
     if (role == AVCT_INT)
     {
+        p_scb = p_cb->p_scb[shdl - 1];
         bda = p_scb->peer_addr;
         status = BTA_AV_RC_ROLE_INT;
     }
@@ -353,9 +406,9 @@
         /* this LIDX is reserved for the AVRCP ACP connection */
         p_cb->rc_acp_handle = p_rcb->handle;
         p_cb->rc_acp_idx = (i + 1);
-        APPL_TRACE_DEBUG("rc_acp_handle:%d idx:%d", p_cb->rc_acp_handle, p_cb->rc_acp_idx);
+        APPL_TRACE_IMP("rc_acp_handle: %d idx: %d", p_cb->rc_acp_handle, p_cb->rc_acp_idx);
     }
-    APPL_TRACE_DEBUG("create %d, role: %d, shdl:%d, rc_handle:%d, lidx:%d, status:0x%x",
+    APPL_TRACE_IMP("bta_av_rc_create %d, role: %d, shdl:%d, rc_handle:%d, lidx:%d, status:0x%x",
         i, role, shdl, p_rcb->handle, lidx, p_rcb->status);
 
     return rc_handle;
@@ -569,12 +622,16 @@
     if (rc_open.peer_features == 0)
     {
         /* we have not done SDP on peer RC capabilities.
-         * peer must have initiated the RC connection
-         * We Don't have SDP records of Peer, so we by
-         * default will take values depending upon registered
-         * features */
-        if (p_cb->features & BTA_AV_FEAT_RCTG)
+         * peer must have initiated the RC connection */
+        /*To update default features based on the local features we support*/
+        if (bta_av_cb.features & BTA_AV_FEAT_RCTG)
+        {
             rc_open.peer_features |= BTA_AV_FEAT_RCCT;
+        }
+        if (bta_av_cb.features & BTA_AV_FEAT_RCCT)
+        {
+            rc_open.peer_features |= BTA_AV_FEAT_RCTG;
+        }
         bta_av_rc_disc(disc);
     }
     (*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open);
@@ -673,7 +730,9 @@
             (!p_data->api_meta_rsp.is_rsp && (p_cb->features & BTA_AV_FEAT_RCCT)) )
         {
             p_rcb = &p_cb->rcb[p_data->hdr.layer_specific];
-            if (p_rcb->handle != BTA_AV_RC_HANDLE_NONE) {
+            /* Fix for below Klockwork Issue
+             * Array 'avrc_cb.fcb' of size 5 may use index value(s) 0..254 */
+            if ((p_rcb->handle != BTA_AV_RC_HANDLE_NONE) && (p_rcb->handle < AVCT_NUM_CONN)) {
                 AVRC_MsgReq(p_rcb->handle, p_data->api_meta_rsp.label,
                             p_data->api_meta_rsp.rsp_code,
                             p_data->api_meta_rsp.p_pkt);
@@ -769,15 +828,25 @@
 tBTA_AV_EVT bta_av_proc_meta_cmd(tAVRC_RESPONSE  *p_rc_rsp, tBTA_AV_RC_MSG *p_msg, UINT8 *p_ctype)
 {
     tBTA_AV_EVT evt = BTA_AV_META_MSG_EVT;
-    UINT8       u8, pdu, *p;
+    UINT8       u8, pdu, *p, i;
     UINT16      u16;
     tAVRC_MSG_VENDOR    *p_vendor = &p_msg->msg.vendor;
+    BD_ADDR     addr;
+    BOOLEAN is_dev_avrcpv_blacklisted = FALSE;
 
 #if (AVRC_METADATA_INCLUDED == TRUE)
 
     pdu = *(p_vendor->p_vendor_data);
     p_rc_rsp->pdu = pdu;
     *p_ctype = AVRC_RSP_REJ;
+    /* Check for valid Meta Length, AVRCP minimum Meta command length 20 */
+    if ((AVRC_MIN_META_CMD_LEN + p_vendor->vendor_len) > AVRC_META_CMD_BUF_SIZE)
+    {
+        /* reject it */
+        p_rc_rsp->rsp.status = AVRC_STS_BAD_PARAM;
+        APPL_TRACE_ERROR("Bailing out: Invalid meta-command length: %d", p_vendor->vendor_len);
+        return 0;
+    }
     /* Metadata messages only use PANEL sub-unit type */
     if (p_vendor->hdr.subunit_type != AVRC_SUB_PANEL)
     {
@@ -829,8 +898,31 @@
                 {
                     *p_ctype = AVRC_RSP_IMPL_STBL;
                     p_rc_rsp->get_caps.count = p_bta_av_cfg->num_evt_ids;
-                    memcpy(p_rc_rsp->get_caps.param.event_id, p_bta_av_cfg->p_meta_evt_ids,
-                           p_bta_av_cfg->num_evt_ids);
+                    /* DUT has blacklisted few remote dev for Avrcp Version hence
+                     * respose for event supported should not have AVRCP 1.5/1.4
+                     * version events
+                     */
+                    if (avct_get_peer_addr_by_ccb(p_msg->handle, addr) == TRUE)
+                    {
+                        is_dev_avrcpv_blacklisted = SDP_Dev_Blacklisted_For_Avrcp15(addr);
+                        BTIF_TRACE_ERROR("Blacklist for AVRCP1.5 = %d", is_dev_avrcpv_blacklisted);
+                    }
+                    BTIF_TRACE_DEBUG("Blacklist for AVRCP1.5 = %d", is_dev_avrcpv_blacklisted);
+                    if (is_dev_avrcpv_blacklisted == TRUE)
+                    {
+                        for (i = 0; i <= p_bta_av_cfg->num_evt_ids; ++i)
+                        {
+                           if (p_bta_av_cfg->p_meta_evt_ids[i] == AVRC_EVT_AVAL_PLAYERS_CHANGE)
+                              break;
+                        }
+                        p_rc_rsp->get_caps.count = i;
+                        memcpy(p_rc_rsp->get_caps.param.event_id, p_bta_av_cfg->p_meta_evt_ids, i);
+                    }
+                    else
+                    {
+                        memcpy(p_rc_rsp->get_caps.param.event_id, p_bta_av_cfg->p_meta_evt_ids,
+                               p_bta_av_cfg->num_evt_ids);
+                    }
                 }
                 else
                 {
@@ -851,7 +943,7 @@
         }
     }
 #else
-    APPL_TRACE_DEBUG("AVRCP 1.3 Metadata not supporteed. Reject command.");
+    BTIF_TRACE_IMP("AVRCP 1.3 Metadata not supporteed. Reject command.");
     /* reject invalid message without reporting to app */
     evt = 0;
     p_rc_rsp->rsp.status = AVRC_STS_BAD_CMD;
@@ -860,6 +952,40 @@
     return evt;
 }
 
+/*****************************************************************************
+**
+** Function        bta_av_proc_browse_cmd
+**
+** Description     Process and AVRCP browse command from the peer
+**
+** Returns         status
+**
+****************************************************************************/
+tBTA_AV_EVT bta_av_proc_browse_cmd(tAVRC_RESPONSE  *p_rc_rsp, tBTA_AV_RC_MSG *p_msg)
+{
+    tBTA_AV_EVT evt = BTA_AV_BROWSE_MSG_EVT;
+    UINT8       pdu;
+    tAVRC_MSG_BROWSE *p_browse = &p_msg->msg.browse;
+
+    pdu = p_browse->p_browse_data[0];
+    APPL_TRACE_DEBUG("bta_av_proc_browse_cmd browse cmd: %x", pdu);
+    switch (pdu)
+    {
+        case AVRC_PDU_GET_FOLDER_ITEMS:
+        case AVRC_PDU_SET_BROWSED_PLAYER:
+        case AVRC_PDU_CHANGE_PATH:
+        case AVRC_PDU_GET_ITEM_ATTRIBUTES:
+        case AVRC_PDU_GET_TOTAL_NUMBER_OF_ITEMS:
+            break;
+        default:
+            evt = 0;
+            p_rc_rsp->rsp.status = AVRC_STS_BAD_CMD;
+            APPL_TRACE_ERROR("### Not supported cmd: %x", pdu);
+            break;
+    }
+    return evt;
+}
+
 /*******************************************************************************
 **
 ** Function         bta_av_rc_msg
@@ -884,6 +1010,7 @@
 
     rc_rsp.rsp.status = BTA_AV_STS_NO_RSP;
 #endif
+    APPL_TRACE_DEBUG("bta_av_rc_msg opcode: %x",p_data->rc_msg.opcode);
 
     if (p_data->rc_msg.opcode == AVRC_OP_PASS_THRU)
     {
@@ -1024,6 +1151,25 @@
            AVRC_VendorRsp(p_data->rc_msg.handle, p_data->rc_msg.label, &p_data->rc_msg.msg.vendor);
         }
     }
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+    else if (p_data->rc_msg.opcode == AVRC_OP_BROWSE )
+    {
+        APPL_TRACE_DEBUG("browse len PDU :%x",p_data->rc_msg.msg.browse.browse_len);
+        APPL_TRACE_DEBUG("browse  data:%x",p_data->rc_msg.msg.browse.p_browse_data[0]);
+        av.browse_msg.label = p_data->rc_msg.label;
+        av.browse_msg.p_msg = &p_data->rc_msg.msg;
+
+        evt = bta_av_proc_browse_cmd(&rc_rsp, &p_data->rc_msg);
+        if (evt == 0)
+        {
+            APPL_TRACE_ERROR("Browse PDU not supported");
+            rc_rsp.rsp.pdu    = AVRC_PDU_GENERAL_REJECT;
+            rc_rsp.rsp.status = AVRC_STS_BAD_CMD;
+            ctype = 0;
+            AVRC_BldBrowseResponse(0, &rc_rsp, &p_pkt);
+        }
+    }
+#endif
 #if (AVRC_METADATA_INCLUDED == TRUE)
     if (evt == 0 && rc_rsp.rsp.status != BTA_AV_STS_NO_RSP)
     {
@@ -1207,7 +1353,10 @@
     BOOLEAN     chk_restore = FALSE;
 
     /* Validate array index*/
-    if (index < BTA_AV_NUM_STRS)
+    /* Fix for below klockwork issue
+     * Array 'p_scb' size is 2.
+     * Possible attempt to access element -1 of array 'p_scb' */
+    if (index >= 0 && index < BTA_AV_NUM_STRS)
     {
         p_scb = p_cb->p_scb[index];
     }
@@ -1408,7 +1557,10 @@
 
     bta_av_close_all_rc(p_cb);
 
-    osi_free_and_reset((void **)&p_cb->p_disc_db);
+    if(p_cb->p_disc_db) {
+	    (void)SDP_CancelServiceSearch (p_cb->p_disc_db);
+        osi_free_and_reset((void **)&p_cb->p_disc_db);
+    }
 
     /* disable audio/video - de-register all channels,
      * expect BTA_AV_DEREG_COMP_EVT when deregister is complete */
@@ -1456,21 +1608,55 @@
     UINT8   mask;
     tBTA_AV_LCB *p_lcb = NULL;
 
-    APPL_TRACE_DEBUG("bta_av_sig_chg event: %d", event);
-    if (event == AVDT_CONNECT_IND_EVT)
+    BTIF_TRACE_IMP("%s bta_av_sig_chg event: %d",
+            __FUNCTION__, event);
+    if(event == AVDT_CONNECT_IND_EVT)
     {
         p_lcb = bta_av_find_lcb(p_data->str_msg.bd_addr, BTA_AV_LCB_FIND);
         if (!p_lcb)
         {
+            if (p_cb->conn_lcb > 0)
+            {
+                APPL_TRACE_DEBUG("Already connected to LCBs: 0x%x", p_cb->conn_lcb);
+            }
+            /* Check if busy processing a connection, if yes, Reject the
+             * new incoming connection.
+             * This is very rare case to happen as the timeout to start
+             * signalling procedure is just 2 sec.
+             * Also sink initiators will have retry machanism.
+             * Even though busy flag is set during outgoing connection to
+             * reject incoming connection at L2CAP connect request, there
+             * is a chance to get here if the incoming connection has passed
+             * the L2CAP connection stage.
+             */
+            if((p_data->hdr.offset == AVDT_ACP) && (AVDT_GetServiceBusyState() == TRUE))
+            {
+                APPL_TRACE_ERROR("%s Incoming conn while processing another.. Reject",
+                    __FUNCTION__);
+                AVDT_DisconnectReq (p_data->str_msg.bd_addr, NULL);
+                return;
+            }
+
             /* if the address does not have an LCB yet, alloc one */
             for(xx=0; xx<BTA_AV_NUM_LINKS; xx++)
             {
                 mask = 1 << xx;
-                APPL_TRACE_DEBUG("conn_lcb: 0x%x", p_cb->conn_lcb);
+                APPL_TRACE_DEBUG("The current conn_lcb: 0x%x", p_cb->conn_lcb);
 
                 /* look for a p_lcb with its p_scb registered */
                 if ((!(mask & p_cb->conn_lcb)) && (p_cb->p_scb[xx] != NULL))
                 {
+                    /* Check if the SCB is Free before using for
+                     * ACP connection
+                     */
+                    if ((p_data->hdr.offset == AVDT_ACP) &&
+                        (p_cb->p_scb[xx]->state != BTA_AV_INIT_SST))
+                    {
+                        APPL_TRACE_DEBUG("SCB in use %d", xx);
+                        continue;
+                    }
+
+                    APPL_TRACE_DEBUG("Found a free p_lcb : 0x%x", xx);
                     p_lcb = &p_cb->lcb[xx];
                     p_lcb->lidx = xx + 1;
                     bdcpy(p_lcb->addr, p_data->str_msg.bd_addr);
@@ -1497,6 +1683,9 @@
                          */
                         bta_av_signalling_timer(NULL);
 
+                        APPL_TRACE_DEBUG("%s: Re-start timer for AVDTP service", __func__);
+                        bta_sys_conn_open(BTA_ID_AV, p_cb->p_scb[xx]->app_id,
+                                p_cb->p_scb[xx]->peer_addr);
                         /* Possible collision : need to avoid outgoing processing while the timer is running */
                         p_cb->p_scb[xx]->coll_mask = BTA_AV_COLL_INC_TMR;
                         alarm_set_on_queue(p_cb->accept_signalling_timer,
@@ -1538,6 +1727,13 @@
             /* clean up ssm  */
             for(xx=0; xx < BTA_AV_NUM_STRS; xx++)
             {
+
+                if ((p_cb->p_scb[xx]) &&
+                        (bdcmp(p_cb->p_scb[xx]->peer_addr, p_data->str_msg.bd_addr) == 0))
+                {
+                    APPL_TRACE_DEBUG("%s: Closing timer for AVDTP service", __func__);
+                    bta_sys_conn_close(BTA_ID_AV, p_cb->p_scb[xx]->app_id,p_cb->p_scb[xx]->peer_addr);
+                }
                 mask = 1 << (xx + 1);
                 if (((mask & p_lcb->conn_msk) || bta_av_cb.conn_lcb) && (p_cb->p_scb[xx]) &&
                     (bdcmp(p_cb->p_scb[xx]->peer_addr, p_data->str_msg.bd_addr) == 0))
@@ -1585,6 +1781,9 @@
                                     BTA_AV_SIGNALLING_TIMEOUT_MS,
                                     BTA_AV_SIGNALLING_TIMER_EVT, 0);
                 bdcpy(pend.bd_addr, p_lcb->addr);
+                APPL_TRACE_DEBUG("bta_av_sig_timer on IDX = %d",xx);
+                //Copy the handle of SCB
+                pend.hndl = p_cb->p_scb[xx]->hndl;
                 (*p_cb->p_cback)(BTA_AV_PENDING_EVT, (tBTA_AV *) &pend);
             }
         }
@@ -1606,6 +1805,7 @@
     UINT32   inx = PTR_TO_UINT(data);
     tBTA_AV_CB  *p_cb = &bta_av_cb;
     tBTA_AV_SCB *p_scb = NULL;
+
     if (inx < BTA_AV_NUM_STRS)
     {
         p_scb = p_cb->p_scb[inx];
@@ -1660,6 +1860,58 @@
     }
 }
 
+BOOLEAN bta_av_check_store_avrc_tg_version(BD_ADDR addr, UINT16 ver)
+{
+    BOOLEAN is_present = FALSE;
+    struct blacklist_entry data;
+    FILE *fp;
+    BOOLEAN is_file_updated = FALSE;
+
+    APPL_TRACE_DEBUG("%s target BD Addr: %x:%x:%x", __func__,\
+                        addr[0], addr[1], addr[2]);
+    fp = fopen(AVRC_PEER_VERSION_CONF_FILE, "rb");
+    if (!fp)
+    {
+      APPL_TRACE_ERROR("%s unable to open AVRC Conf file for read: error: (%s)",\
+                                                        __func__, strerror(errno));
+    }
+    else
+    {
+        while (fread(&data, sizeof(data), 1, fp) != 0)
+        {
+            APPL_TRACE_DEBUG("Entry: addr = %x:%x:%x, ver = 0x%x",\
+                    data.addr[0], data.addr[1], data.addr[2], data.ver);
+            if(!memcmp(addr, data.addr, 3))
+            {
+                is_present = TRUE;
+                APPL_TRACE_DEBUG("Entry alreday present, bailing out");
+                break;
+            }
+        }
+        fclose(fp);
+    }
+
+    if (is_present == FALSE)
+    {
+        fp = fopen(AVRC_PEER_VERSION_CONF_FILE, "ab");
+        if (!fp)
+        {
+            APPL_TRACE_ERROR("%s unable to open AVRC Conf file for write: error: (%s)",\
+                                                              __func__, strerror(errno));
+        }
+        else
+        {
+            data.ver = ver;
+            memcpy(data.addr, (const char *)addr, 3);
+            APPL_TRACE_DEBUG("Avrcp version to store = 0x%x", ver);
+            fwrite(&data, sizeof(data), 1, fp);
+            fclose(fp);
+            is_file_updated = TRUE;
+        }
+    }
+    return is_file_updated;
+}
+
 /*******************************************************************************
 **
 ** Function         bta_av_check_peer_features
@@ -1676,7 +1928,7 @@
     tBTA_AV_CB   *p_cb = &bta_av_cb;
     tSDP_DISC_REC       *p_rec = NULL;
     tSDP_DISC_ATTR      *p_attr;
-    UINT16              peer_rc_version=0;
+    UINT16              peer_rc_version=0; /*Assuming Default peer version as 1.3*/
     UINT16              categories = 0;
 
     APPL_TRACE_DEBUG("bta_av_check_peer_features service_uuid:x%x", service_uuid);
@@ -1707,6 +1959,22 @@
             /* get profile version (if failure, version parameter is not updated) */
             SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_AV_REMOTE_CONTROL,
                                                                 &peer_rc_version);
+
+            if (interop_match_addr(INTEROP_ADV_AVRCP_VER_1_3,
+                    (const bt_bdaddr_t*) p_rec->remote_bd_addr))
+            {
+                peer_rc_version = AVRC_REV_1_3;
+                APPL_TRACE_DEBUG("changing peer_rc_version as part of blacklisting to 0x%x",
+                        peer_rc_version);
+            }
+            else if (interop_match_addr(INTEROP_STORE_REMOTE_AVRCP_VERSION_1_4,
+                    (const bt_bdaddr_t*) p_rec->remote_bd_addr))
+            {
+                peer_rc_version = AVRC_REV_1_4;
+                APPL_TRACE_DEBUG("changing peer_rc_version as part of blacklisting to 0x%x",
+                        peer_rc_version);
+            }
+
             APPL_TRACE_DEBUG("peer_rc_version 0x%x", peer_rc_version);
 
             if (peer_rc_version >= AVRC_REV_1_3)
@@ -1721,9 +1989,39 @@
                 {
                     categories = p_attr->attr_value.v.u16;
                     if (categories & AVRC_SUPF_CT_BROWSE)
+                    {
                         peer_features |= (BTA_AV_FEAT_BROWSE);
+                        APPL_TRACE_DEBUG("peer supports browsing");
+                    }
+                    if (categories & AVRC_SUPF_CT_COVER_ART_GET_IMAGE &
+                        AVRC_SUPF_CT_COVER_ART_GET_THUMBNAIL)
+                    {
+                        peer_features |=  BTA_AV_FEAT_CA;
+                        APPL_TRACE_DEBUG("peer supports cover art");
+                    }
                 }
             }
+#if ((defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE)) || \
+           (defined(SDP_AVRCP_1_5) && (SDP_AVRCP_1_5 == TRUE)))
+            if ((peer_rc_version >= AVRC_REV_1_4) &&
+                    ((peer_features & BTA_AV_FEAT_BROWSE) || (peer_features & BTA_AV_FEAT_CA)))
+            {
+                BOOLEAN ret = FALSE;
+                APPL_TRACE_DEBUG("peer version to update: 0x%x", peer_rc_version);
+                ret = bta_av_check_store_avrc_tg_version(p_rec->remote_bd_addr, peer_rc_version);
+                if (ret == TRUE)
+                {
+                    peer_features |= BTA_AV_FEAT_AVRC_UI_UPDATE;
+                    APPL_TRACE_DEBUG("update UI on peer repair request: 0x%x",
+                                    peer_features);
+                }
+            }
+            else
+            {
+                APPL_TRACE_DEBUG("No need to store peer version: 0x%x", peer_rc_version);
+                /*No need to update peer version as we send the default version as 1.3*/
+            }
+#endif
         }
     }
     APPL_TRACE_DEBUG("peer_features:x%x", peer_features);
@@ -1744,61 +2042,64 @@
 {
     tBTA_AV_FEAT peer_features = 0;
     tBTA_AV_CB *p_cb = &bta_av_cb;
+    tSDP_DISC_REC *p_rec = NULL;
+    tSDP_DISC_ATTR *p_attr;
+    UINT16 peer_rc_version = 0;
+    UINT16 categories = 0;
+    BOOLEAN val;
 
     APPL_TRACE_DEBUG("%s service_uuid:x%x", __FUNCTION__, service_uuid);
-
-    /* loop through all records we found */
-    tSDP_DISC_REC *p_rec = SDP_FindServiceInDb(p_cb->p_disc_db, service_uuid, NULL);
-    while (p_rec)
+    /* get next record; if none found, we're done */
+    p_rec = SDP_FindServiceInDb(p_cb->p_disc_db, service_uuid, p_rec);
+    if (p_rec != NULL)
     {
-        APPL_TRACE_DEBUG("%s found Service record for x%x", __FUNCTION__, service_uuid);
+        APPL_TRACE_DEBUG(" %s found Service record for x%x", __FUNCTION__, service_uuid);
+        if (service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL)
+             peer_features |= BTA_AV_FEAT_RCCT;
+        else if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET)
+             peer_features |= BTA_AV_FEAT_RCTG;
 
-        if (( SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_CLASS_ID_LIST)) != NULL)
-        {
-            /* find peer features */
-            if (SDP_FindServiceInDb(p_cb->p_disc_db, UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL))
-            {
-                peer_features |= BTA_AV_FEAT_RCCT;
-            }
-            if (SDP_FindServiceInDb(p_cb->p_disc_db, UUID_SERVCLASS_AV_REM_CTRL_TARGET, NULL))
-            {
-                peer_features |= BTA_AV_FEAT_RCTG;
-            }
+         if ((SDP_FindAttributeInRec(p_rec, ATTR_ID_BT_PROFILE_DESC_LIST)) != NULL)
+         {
+             /* profile version (if failure, version parameter is not updated) */
+             val = SDP_FindProfileVersionInRec(p_rec,
+                       UUID_SERVCLASS_AV_REMOTE_CONTROL, &peer_rc_version);
+             APPL_TRACE_DEBUG("%s rc_version for TG 0x%x, profile_found %d", __FUNCTION__,
+                                                     peer_rc_version, val);
+
+             if (peer_rc_version < AVRC_REV_1_3)
+                return peer_features;
+
+             p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FEATURES);
+             if (p_attr == NULL)
+                 return peer_features;
+
+             categories = p_attr->attr_value.v.u16;
+
+             if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET)
+             {
+                 peer_features |= (BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_METADATA);
+                 /* get supported categories */
+                 if (categories & AVRC_SUPF_CT_BROWSE)
+                     peer_features |= BTA_AV_FEAT_BROWSE;
+                 if (categories & AVRC_SUPF_CT_APP_SETTINGS)
+                     peer_features |= BTA_AV_FEAT_APP_SETTING;
+             }
+             /*
+              * Absolute Volume came after in 1.4 and above.
+              * but there are few devices in market which supports.
+              * absoluteVolume and they are still 1.3 To avoid inter-operatibility issuses with.
+              * those devices, we check for 1.3 as minimum version.
+              */
+             else if (service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL)
+             {
+                 if (categories & AVRC_SUPF_CT_CAT2)
+                 {
+                     APPL_TRACE_DEBUG(" %s Remote supports ABS Vol", __FUNCTION__);
+                     peer_features |= BTA_AV_FEAT_ADV_CTRL;
+                 }
+             }
         }
-
-        if (( SDP_FindAttributeInRec(p_rec, ATTR_ID_BT_PROFILE_DESC_LIST)) != NULL)
-        {
-            /* get profile version (if failure, version parameter is not updated) */
-            UINT16 peer_rc_version = 0;
-            BOOLEAN val = SDP_FindProfileVersionInRec(
-                p_rec, UUID_SERVCLASS_AV_REMOTE_CONTROL, &peer_rc_version);
-            APPL_TRACE_DEBUG("%s peer_rc_version for TG 0x%x, profile_found %d",
-                             __FUNCTION__, peer_rc_version, val);
-
-            if (peer_rc_version >= AVRC_REV_1_3)
-                peer_features |= (BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_METADATA);
-
-            /*
-             * Though Absolute Volume came after in 1.4 and above, but there are few devices
-             * in market which supports absolute Volume and they are still 1.3
-             * TO avoid IOT issuses with those devices, we check for 1.3 as minimum version
-             */
-            if (peer_rc_version >= AVRC_REV_1_3)
-            {
-                /* get supported categories */
-                tSDP_DISC_ATTR *p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FEATURES);
-                if (p_attr != NULL)
-                {
-                    UINT16 categories = p_attr->attr_value.v.u16;
-                    if (categories & AVRC_SUPF_CT_CAT2)
-                        peer_features |= (BTA_AV_FEAT_ADV_CTRL);
-                    if (categories & AVRC_SUPF_CT_APP_SETTINGS)
-                        peer_features |= (BTA_AV_FEAT_APP_SETTING);
-                }
-            }
-        }
-        /* get next record; if none found, we're done */
-        p_rec = SDP_FindServiceInDb(p_cb->p_disc_db, service_uuid, p_rec);
     }
     APPL_TRACE_DEBUG("%s peer_features:x%x", __FUNCTION__, peer_features);
     return peer_features;
@@ -1839,7 +2140,10 @@
     else
     {
         /* Validate array index*/
-        if (((p_cb->disc & BTA_AV_HNDL_MSK) - 1) < BTA_AV_NUM_STRS)
+        /* Fix for below klockwork issue
+         * Array 'p_scb' size is 2
+         * Possible attempt to access element -1 of array 'p_scb' */
+        if ((((p_cb->disc & BTA_AV_HNDL_MSK) - 1) < BTA_AV_NUM_STRS) && (((p_cb->disc & BTA_AV_HNDL_MSK) - 1) >= 0))
         {
             p_scb = p_cb->p_scb[(p_cb->disc & BTA_AV_HNDL_MSK) - 1];
         }
@@ -1855,13 +2159,22 @@
     }
 
     APPL_TRACE_DEBUG("%s rc_handle %d", __FUNCTION__, rc_handle);
+    if (rc_handle == BTA_AV_RC_HANDLE_NONE)
+    {
+        if (AVRC_CheckIncomingConn(p_scb->peer_addr) == TRUE)
+        {
+            bta_sys_start_timer(p_scb->avrc_ct_timer, AVRC_CONNECT_RETRY_DELAY_MS,
+                                   BTA_AV_SDP_AVRC_DISC_EVT,p_scb->hndl);
+        }
+    }
+
 #if (BTA_AV_SINK_INCLUDED == TRUE)
     if (p_cb->sdp_a2d_snk_handle)
     {
         /* This is Sink + CT + TG(Abs Vol) */
-        peer_features = bta_avk_check_peer_features(UUID_SERVCLASS_AV_REM_CTRL_TARGET);
-        if (BTA_AV_FEAT_ADV_CTRL & bta_avk_check_peer_features(UUID_SERVCLASS_AV_REMOTE_CONTROL))
-            peer_features |= (BTA_AV_FEAT_ADV_CTRL|BTA_AV_FEAT_RCCT);
+        peer_features = bta_avk_check_peer_features(UUID_SERVCLASS_AV_REMOTE_CONTROL);
+        peer_features |= bta_avk_check_peer_features(UUID_SERVCLASS_AV_REM_CTRL_TARGET);
+        APPL_TRACE_DEBUG("final rc_features %x", peer_features);
     }
     else
 #endif
@@ -1896,7 +2209,22 @@
                 if (p_lcb)
                 {
                     rc_handle = bta_av_rc_create(p_cb, AVCT_INT, (UINT8)(p_scb->hdi + 1), p_lcb->lidx);
-                    p_cb->rcb[rc_handle].peer_features = peer_features;
+                    /* Fix for below Klockwork Issue
+                     * Array 'rcb' of size 4 may use index value(s) 4..254 */
+                    if((rc_handle != BTA_AV_RC_HANDLE_NONE) && (rc_handle < BTA_AV_NUM_RCB))
+                    {
+                        p_cb->rcb[rc_handle].peer_features = peer_features;
+                    }
+                    else
+                    {
+                        /* cannot create valid rc_handle for current device */
+                        APPL_TRACE_ERROR(" No link resources available");
+                        p_scb->use_rc = FALSE;
+                        bdcpy(rc_open.peer_addr, p_scb->peer_addr);
+                        rc_open.peer_features = 0;
+                        rc_open.status = BTA_AV_FAIL_RESOURCES;
+                        (*p_cb->p_cback)(BTA_AV_RC_CLOSE_EVT, (tBTA_AV *) &rc_open);
+                    }
                 }
 #if (BT_USE_TRACES == TRUE || BT_TRACE_APPL == TRUE)
                 else
@@ -1918,7 +2246,10 @@
     }
     else
     {
-        p_cb->rcb[rc_handle].peer_features = peer_features;
+        /* Fix for below Klockwork Issue
+         * Array 'rcb' of size 4 may use index value(s) 4..254 */
+        if (rc_handle < BTA_AV_NUM_RCB)
+            p_cb->rcb[rc_handle].peer_features = peer_features;
         rc_feat.rc_handle =  rc_handle;
         rc_feat.peer_features = peer_features;
         if (p_scb == NULL)
@@ -1938,6 +2269,26 @@
 
 /*******************************************************************************
 **
+** Function         bta_av_rc_collission_detected
+**
+** Description      Update App on collision detected case
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rc_collission_detected(tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_CB   *p_cb = &bta_av_cb;
+    tBTA_AV_RC_COLL_DETECTED rc_coll;
+    tBTA_AV_RC_COLLISSION_DETECTED *p_msg = (tBTA_AV_RC_COLLISSION_DETECTED *)p_data;
+    rc_coll.rc_handle = p_msg->handle;
+    bdcpy(rc_coll.peer_addr, p_msg->peer_addr);
+    (*p_cb->p_cback)(BTA_AV_RC_COLL_DETECTED_EVT, (tBTA_AV *) &rc_coll);
+}
+
+/*******************************************************************************
+**
 ** Function         bta_av_rc_closed
 **
 ** Description      Set AVRCP state to closed.
@@ -2008,10 +2359,6 @@
             {
                 /* AVCT CCB is still there. dealloc */
                 bta_av_del_rc(p_rcb);
-
-                /* if the AVRCP is no longer listening, create the listening channel */
-                if (bta_av_cb.rc_acp_handle == BTA_AV_RC_HANDLE_NONE && bta_av_cb.features & BTA_AV_FEAT_RCTG)
-                    bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
             }
         }
         else if ((p_rcb->handle != BTA_AV_RC_HANDLE_NONE) && (p_rcb->status & BTA_AV_RC_CONN_MASK))
@@ -2033,6 +2380,9 @@
         bdcpy(rc_close.peer_addr, p_msg->peer_addr);
     }
     (*p_cb->p_cback)(BTA_AV_RC_CLOSE_EVT, (tBTA_AV *) &rc_close);
+    if (bta_av_cb.rc_acp_handle == BTA_AV_RC_HANDLE_NONE
+                    && bta_av_cb.features & BTA_AV_FEAT_RCTG)
+        bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
 }
 
 /*******************************************************************************
diff --git a/bta/av/bta_av_api.c b/bta/av/bta_av_api.c
index 5a033c9..60e3eb9 100644
--- a/bta/av/bta_av_api.c
+++ b/bta/av/bta_av_api.c
@@ -223,11 +223,12 @@
 ** Returns          void
 **
 *******************************************************************************/
-void BTA_AvStart(void)
+void BTA_AvStart(tBTA_AV_HNDL handle)
 {
     BT_HDR *p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR));
 
     p_buf->event = BTA_AV_API_START_EVT;
+    p_buf->layer_specific   = handle;
 
     bta_sys_sendmsg(p_buf);
 }
@@ -305,7 +306,7 @@
 ** Returns          void
 **
 *******************************************************************************/
-void BTA_AvStop(BOOLEAN suspend)
+void BTA_AvStop(BOOLEAN suspend, tBTA_AV_HNDL handle)
 {
     tBTA_AV_API_STOP *p_buf =
         (tBTA_AV_API_STOP *)osi_malloc(sizeof(tBTA_AV_API_STOP));
@@ -313,12 +314,55 @@
     p_buf->hdr.event = BTA_AV_API_STOP_EVT;
     p_buf->flush = TRUE;
     p_buf->suspend = suspend;
+    p_buf->hdr.layer_specific   = handle;
 
     bta_sys_sendmsg(p_buf);
 }
 
 /*******************************************************************************
 **
+** Function         BTA_AvEnableMultiCast
+**
+** Description      Enable/Disable Avdtp MultiCast
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvEnableMultiCast(BOOLEAN state, tBTA_AV_HNDL handle)
+{
+    tBTA_AV_ENABLE_MULTICAST  *p_buf;
+
+    if ((p_buf = (tBTA_AV_ENABLE_MULTICAST *) osi_malloc(sizeof(tBTA_AV_ENABLE_MULTICAST))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_ENABLE_MULTICAST_EVT;
+        p_buf->hdr.layer_specific   = handle;
+        p_buf->is_multicast_enabled = state;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvUpdateMaxAVClient
+**
+** Description      Update max av connections supported simultaneously
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvUpdateMaxAVClient(UINT8 max_clients)
+{
+    tBTA_AV_MAX_CLIENT *p_buf;
+
+    if ((p_buf = (tBTA_AV_MAX_CLIENT *) osi_malloc(sizeof(tBTA_AV_MAX_CLIENT))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_UPDATE_MAX_AV_CLIENTS_EVT;
+        p_buf->max_clients = max_clients;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+/*******************************************************************************
+**
 ** Function         BTA_AvReconfig
 **
 ** Description      Reconfigure the audio/video stream.
diff --git a/bta/av/bta_av_cfg.c b/bta/av/bta_av_cfg.c
index e2a8aa8..0c3011b 100644
--- a/bta/av/bta_av_cfg.c
+++ b/bta/av/bta_av_cfg.c
@@ -41,6 +41,8 @@
 
 /* AVRCP cupported categories */
 #if (AVRC_CTLR_INCLUDED == TRUE)
+#define BTA_AV_RC_SUPF_CT       (AVRC_SUPF_CT_CAT1 | AVRC_SUPF_CT_CAT2)
+#else
 #define BTA_AV_RC_SUPF_CT       (AVRC_SUPF_CT_CAT2)
 #endif
 
@@ -68,21 +70,37 @@
 /* Note: Android doesnt support AVRC_SUPF_TG_GROUP_NAVI  */
 /* Note: if AVRC_SUPF_TG_GROUP_NAVI is set, bta_av_cfg.avrc_group should be TRUE */
 #if AVRC_METADATA_INCLUDED == TRUE
-#define BTA_AV_RC_SUPF_TG       (AVRC_SUPF_TG_CAT1) /* TODO: | AVRC_SUPF_TG_APP_SETTINGS) */
+
+#if AVCT_BROWSE_INCLUDED == TRUE
+#if (defined(AVCT_COVER_ART_INCLUDED) && (AVCT_COVER_ART_INCLUDED == TRUE))
+#define BTA_AV_RC_SUPF_TG       (AVRC_SUPF_TG_CAT1 | AVRC_SUPF_TG_BROWSE | AVRC_SUPF_TG_APP_SETTINGS | AVRC_SUPF_TG_PLAYER_COVER_ART)
+#else
+#define BTA_AV_RC_SUPF_TG       (AVRC_SUPF_TG_CAT1 | AVRC_SUPF_TG_BROWSE | AVRC_SUPF_TG_APP_SETTINGS)
+#endif
+
+#else
+#define BTA_AV_RC_SUPF_TG       (AVRC_SUPF_TG_CAT1 | AVRC_SUPF_TG_APP_SETTINGS)
+#endif
+
 #else
 #define BTA_AV_RC_SUPF_TG       (AVRC_SUPF_TG_CAT1)
 #endif
 
 /*
  * If the number of event IDs is changed in this array, BTA_AV_ NUM_RC_EVT_IDS   also needs to be changed.
+ * AVRCP 1.3 specific events to be added before AVCT_BROWSE_INCLUDED.
  */
 const UINT8  bta_av_meta_caps_evt_ids[] = {
     AVRC_EVT_PLAY_STATUS_CHANGE,
     AVRC_EVT_TRACK_CHANGE,
     AVRC_EVT_PLAY_POS_CHANGED,
-    /* TODO: Add support for these events
     AVRC_EVT_APP_SETTING_CHANGE,
-    */
+#if AVCT_BROWSE_INCLUDED == TRUE
+    AVRC_EVT_NOW_PLAYING_CHANGE,
+    AVRC_EVT_AVAL_PLAYERS_CHANGE,
+    AVRC_EVT_ADDR_PLAYER_CHANGE,
+    AVRC_EVT_NOW_PLAYING_CHANGE,
+#endif
 };
 #ifndef BTA_AV_NUM_RC_EVT_IDS
 #define BTA_AV_NUM_RC_EVT_IDS   (sizeof(bta_av_meta_caps_evt_ids) / sizeof(bta_av_meta_caps_evt_ids[0]))
diff --git a/bta/av/bta_av_int.h b/bta/av/bta_av_int.h
index dbe4c77..a751f14 100644
--- a/bta/av/bta_av_int.h
+++ b/bta/av/bta_av_int.h
@@ -1,4 +1,10 @@
 /******************************************************************************
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a contribution.
+ ******************************************************************************/
+
+/******************************************************************************
  *
  *  Copyright (C) 2004-2012 Broadcom Corporation
  *
@@ -106,7 +112,10 @@
     BTA_AV_AVDT_RPT_CONN_EVT,
 #endif
     BTA_AV_API_START_EVT,       /* the following 2 events must be in the same order as the *AP_*EVT */
-    BTA_AV_API_STOP_EVT
+    BTA_AV_API_STOP_EVT,
+    BTA_AV_UPDATE_MAX_AV_CLIENTS_EVT,
+    BTA_AV_ENABLE_MULTICAST_EVT, /* Event for enable and disable multicast */
+    BTA_AV_RC_COLLISSION_DETECTED_EVT
 };
 
 /* events for AV control block state machine */
@@ -118,13 +127,13 @@
 
 /* events that do not go through state machine */
 #define BTA_AV_FIRST_NSM_EVT    BTA_AV_API_ENABLE_EVT
-#define BTA_AV_LAST_NSM_EVT     BTA_AV_API_STOP_EVT
+#define BTA_AV_LAST_NSM_EVT     BTA_AV_ENABLE_MULTICAST_EVT
 
 /* API events passed to both SSMs (by bta_av_api_to_ssm) */
 #define BTA_AV_FIRST_A2S_API_EVT    BTA_AV_API_START_EVT
 #define BTA_AV_FIRST_A2S_SSM_EVT    BTA_AV_AP_START_EVT
 
-#define BTA_AV_LAST_EVT             BTA_AV_API_STOP_EVT
+#define BTA_AV_LAST_EVT             BTA_AV_ENABLE_MULTICAST_EVT
 
 /* maximum number of SEPS in stream discovery results */
 #define BTA_AV_NUM_SEPS         32
@@ -154,7 +163,6 @@
 #define BTA_AV_MULTI_AV_SUPPORTED   0x01
 #define BTA_AV_MULTI_AV_IN_USE      0x02
 
-
 /*****************************************************************************
 **  Data types
 *****************************************************************************/
@@ -180,6 +188,8 @@
 typedef void * (*tBTA_AV_CO_DATAPATH) (tBTA_AV_CODEC codec_type,
                                        UINT32 *p_len, UINT32 *p_timestamp);
 typedef void (*tBTA_AV_CO_DELAY) (tBTA_AV_HNDL hndl, UINT16 delay);
+typedef BOOLEAN (*tBTA_AV_CO_OFFLOAD_SUPPORT) (void);
+typedef BOOLEAN (*tBTA_AV_CO_OFFLOAD_CAP) (int codec);
 
 /* the call-out functions for one stream */
 typedef struct
@@ -194,6 +204,8 @@
     tBTA_AV_CO_STOP     stop;
     tBTA_AV_CO_DATAPATH data;
     tBTA_AV_CO_DELAY    delay;
+    tBTA_AV_CO_OFFLOAD_SUPPORT offload;
+    tBTA_AV_CO_OFFLOAD_CAP cap;
 } tBTA_AV_CO_FUNCTS;
 
 /* data type for BTA_AV_API_ENABLE_EVT */
@@ -243,6 +255,20 @@
     BOOLEAN             flush;
 } tBTA_AV_API_STOP;
 
+/* data type for BTA_AV_ENABLE_MULTICAST_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BOOLEAN             is_multicast_enabled;
+} tBTA_AV_ENABLE_MULTICAST;
+
+/* data type for BTA_AV_UPDATE_MAX_AV_CLIENTS_EVTT */
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT8               max_clients;
+} tBTA_AV_MAX_CLIENT;
+
 /* data type for BTA_AV_API_DISCONNECT_EVT */
 typedef struct
 {
@@ -359,6 +385,14 @@
     UINT8               handle;
 } tBTA_AV_RC_CONN_CHG;
 
+/* data type for BTA_AV_AVRC_COLL_DETECTED_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_ADDR             peer_addr;
+    UINT8               handle;
+} tBTA_AV_RC_COLLISSION_DETECTED;
+
 /* data type for BTA_AV_CONN_CHG_EVT */
 typedef struct
 {
@@ -397,6 +431,8 @@
     tBTA_AV_CODEC       codec_type;        /* codec type */
     UINT8               tsep;              /* SEP type of local SEP */
     tBTA_AV_DATA_CBACK  *p_app_data_cback; /* Application callback for media packets */
+    UINT32              vendorId;          /* vendorId type */
+    UINT16              codecId;           /* codecId type */
 } tBTA_AV_SEP;
 
 
@@ -434,6 +470,8 @@
     tBTA_AV_SDP_RES         sdp_res;
     tBTA_AV_API_META_RSP    api_meta_rsp;
     tBTA_AV_API_STATUS_RSP  api_status_rsp;
+    tBTA_AV_ENABLE_MULTICAST  multicast_state;
+    tBTA_AV_MAX_CLIENT      max_av_clients;
 } tBTA_AV_DATA;
 
 typedef void (tBTA_AV_VDP_DATA_ACT)(void *p_scb);
@@ -473,6 +511,7 @@
 /* Bitmap for collision, coll_mask */
 #define BTA_AV_COLL_INC_TMR             0x01 /* Timer is running for incoming L2C connection */
 #define BTA_AV_COLL_API_CALLED          0x02 /* API open was called while incoming timer is running */
+#define BTA_AV_COLL_SETCONFIG_IND    0x04 /* SetConfig indication has been called by remote */
 
 /* type for AV stream control block */
 typedef struct
@@ -519,6 +558,7 @@
     UINT8               co_started;     /* non-zero, if stream started from call-out perspective */
     BOOLEAN             recfg_sup;      /* TRUE if the first attempt to reconfigure the stream was successfull, else False if command fails */
     BOOLEAN             suspend_sup;    /* TRUE if Suspend stream is supported, else FALSE if suspend command fails */
+    BOOLEAN             suspend_local_sent;    /* TRUE if outgoing Suspend is sent, else FALSE if confirmation is received */
     BOOLEAN             deregistring;   /* TRUE if deregistering */
     BOOLEAN             sco_suspend;    /* TRUE if SUSPEND is issued automatically for SCO */
     UINT8               coll_mask;      /* Mask to check incoming and outgoing collision */
@@ -601,6 +641,7 @@
     BOOLEAN             sco_occupied;   /* TRUE if SCO is being used or call is in progress */
     UINT8               audio_streams;  /* handle mask of streaming audio channels */
     UINT8               video_streams;  /* handle mask of streaming video channels */
+    UINT8               codec_type;     /* p_scb->codec_type */
 } tBTA_AV_CB;
 
 
@@ -649,7 +690,7 @@
 extern BOOLEAN bta_av_is_scb_init (tBTA_AV_SCB *p_scb);
 extern void bta_av_set_scb_sst_incoming (tBTA_AV_SCB *p_scb);
 extern tBTA_AV_LCB * bta_av_find_lcb(BD_ADDR addr, UINT8 op);
-
+extern BOOLEAN bta_av_is_multicast_enabled();
 
 /* main functions */
 extern void bta_av_api_deregister(tBTA_AV_DATA *p_data);
@@ -673,6 +714,7 @@
 extern void bta_av_rc_disc(UINT8 disc);
 extern void bta_av_conn_chg(tBTA_AV_DATA *p_data);
 extern void bta_av_dereg_comp(tBTA_AV_DATA *p_data);
+extern void bta_av_rc_collission_detected(tBTA_AV_DATA *p_data);
 
 /* sm action functions */
 extern void bta_av_disable (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
diff --git a/bta/av/bta_av_main.c b/bta/av/bta_av_main.c
index 735ee2c..50b116d 100644
--- a/bta/av/bta_av_main.c
+++ b/bta/av/bta_av_main.c
@@ -1,4 +1,9 @@
 /******************************************************************************
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a contribution.
+ ******************************************************************************/
+/******************************************************************************
  *
  *  Copyright (C) 2004-2012 Broadcom Corporation
  *
@@ -29,6 +34,7 @@
 
 #include "bt_target.h"
 #include "osi/include/log.h"
+#include <cutils/properties.h>
 
 #if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE)
 #include "bta_av_co.h"
@@ -36,11 +42,15 @@
 #include "l2c_api.h"
 #include "l2cdefs.h"
 #include "utl.h"
+#include "btm_int.h"
 
 #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
 #include "bta_ar_api.h"
 #endif
 
+#include "a2d_aptx.h"
+#include "a2d_aptx_hd.h"
+
 /*****************************************************************************
 ** Constants and types
 *****************************************************************************/
@@ -65,6 +75,14 @@
 #define BTA_AV_RS_TIME_VAL     1000
 #endif
 
+/* offload codecs support */
+enum
+{
+    APTX = 1,
+    AAC,
+    APTXHD
+};
+
 /* state machine states */
 enum
 {
@@ -123,7 +141,7 @@
 /* API_VENDOR_CMD_EVT */    {BTA_AV_IGNORE,         BTA_AV_INIT_ST },
 /* API_VENDOR_RSP_EVT */    {BTA_AV_IGNORE,         BTA_AV_INIT_ST },
 /* API_META_RSP_EVT */      {BTA_AV_RC_FREE_RSP,    BTA_AV_INIT_ST },
-/* API_RC_CLOSE_EVT */      {BTA_AV_IGNORE,         BTA_AV_INIT_ST },
+/* API_RC_CLOSE_EVT */      {BTA_AV_RC_CLOSE,       BTA_AV_INIT_ST },
 /* AVRC_OPEN_EVT */         {BTA_AV_RC_OPENED,      BTA_AV_OPEN_ST },
 /* AVRC_MSG_EVT */          {BTA_AV_RC_FREE_MSG,    BTA_AV_INIT_ST },
 /* AVRC_NONE_EVT */         {BTA_AV_IGNORE,         BTA_AV_INIT_ST },
@@ -170,6 +188,9 @@
                                  app_id, BD_ADDR peer_addr);
 static void bta_av_sys_rs_cback (tBTA_SYS_CONN_STATUS status,UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
 
+static void bta_av_api_enable_multicast(tBTA_AV_DATA *p_data);
+static void bta_av_api_update_max_av_clients(tBTA_AV_DATA * p_data);
+
 /* action functions */
 const tBTA_AV_NSM_ACT bta_av_nsm_act[] =
 {
@@ -185,13 +206,16 @@
     bta_av_conn_chg,        /* BTA_AV_CONN_CHG_EVT */
     bta_av_dereg_comp,      /* BTA_AV_DEREG_COMP_EVT */
 #if (BTA_AV_SINK_INCLUDED == TRUE)
-    bta_av_api_sink_enable, /* BTA_AV_API_SINK_ENABLE_EVT */
+    bta_av_api_sink_enable,         /* BTA_AV_API_SINK_ENABLE_EVT */
 #endif
 #if (AVDT_REPORTING == TRUE)
-    bta_av_rpc_conn,        /* BTA_AV_AVDT_RPT_CONN_EVT */
+    bta_av_rpc_conn,                /* BTA_AV_AVDT_RPT_CONN_EVT */
 #endif
-    bta_av_api_to_ssm,      /* BTA_AV_API_START_EVT */
-    bta_av_api_to_ssm,      /* BTA_AV_API_STOP_EVT */
+    bta_av_api_to_ssm,              /* BTA_AV_API_START_EVT */
+    bta_av_api_to_ssm,              /* BTA_AV_API_STOP_EVT */
+    bta_av_api_update_max_av_clients,
+    bta_av_api_enable_multicast,    /* BTA_AV_ENABLE_MULTICAST_EVT */
+    bta_av_rc_collission_detected, /* BTA_AV_RC_COLLISSION_DETECTED_EVT */
 };
 
 /*****************************************************************************
@@ -207,6 +231,7 @@
 static char *bta_av_st_code(UINT8 state);
 #endif
 
+static BOOLEAN is_multicast_enabled = FALSE;
 /*******************************************************************************
 **
 ** Function         bta_av_api_enable
@@ -358,6 +383,7 @@
                 p_ret->a2d_list = list_new(NULL);
                 p_ret->avrc_ct_timer = alarm_new("bta_av.avrc_ct_timer");
                 bta_av_cb.p_scb[xx] = p_ret;
+                APPL_TRACE_EVENT("AV: Alloc success, handle is =%d", p_ret->hndl);
                 break;
             }
         }
@@ -492,7 +518,10 @@
     char            *p_service_name;
     tBTA_AV_CODEC   codec_type;
     tBTA_UTL_COD    cod;
-    UINT8           index = 0;
+    UINT8           startIndex = 0;
+    UINT8           endIndex = 0;
+    UINT8           index;
+    UINT16          profile_initialized;
 
     memset(&cs,0,sizeof(tAVDT_CS));
 
@@ -500,8 +529,10 @@
     registr.app_id = p_data->api_reg.app_id;
     registr.chnl   = (tBTA_AV_CHNL)p_data->hdr.layer_specific;
 
-    UINT16 profile_initialized = p_data->api_reg.service_uuid;
-    if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK)
+    APPL_TRACE_DEBUG("bta_av_api_register : channel %d", registr.chnl);
+
+    profile_initialized = p_data->api_reg.service_uuid;
+    if(profile_initialized == UUID_SERVCLASS_AUDIO_SINK)
     {
         p_bta_av_cfg  = (tBTA_AV_CFG *) &bta_avk_cfg;
     }
@@ -513,6 +544,7 @@
     do
     {
         p_scb = bta_av_alloc_scb(registr.chnl);
+        cs.registration_id = p_scb->hdi;
         if(p_scb == NULL)
         {
             APPL_TRACE_ERROR("failed to alloc SCB");
@@ -552,9 +584,21 @@
 #endif
                 if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE)
                 {
+#if (defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE))
+                    bta_ar_reg_avrc(UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target",
+                                   NULL, p_bta_av_cfg->avrc_tg_cat, BTA_ID_AV,
+                                   (bta_av_cb.features & BTA_AV_FEAT_BROWSE), AVRC_REV_1_6);
+#else
+#if (defined(SDP_AVRCP_1_5) && (SDP_AVRCP_1_5 == TRUE))
+                    bta_ar_reg_avrc(UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target",
+                                   NULL, p_bta_av_cfg->avrc_tg_cat, BTA_ID_AV,
+                                   (bta_av_cb.features & BTA_AV_FEAT_BROWSE), AVRC_REV_1_5);
+#else
                     bta_ar_reg_avrc(UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target",
                                    NULL, p_bta_av_cfg->avrc_tg_cat, BTA_ID_AV,
                                    (bta_av_cb.features & BTA_AV_FEAT_BROWSE), AVRC_REV_1_3);
+#endif
+#endif
                 }
                 else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK)
                 {
@@ -605,6 +649,7 @@
         if(registr.chnl == BTA_AV_CHNL_AUDIO)
         {
             /* set up the audio stream control block */
+            APPL_TRACE_EVENT("AV: set up the audio stream control block ");
             p_scb->p_act_tbl = (const tBTA_AV_ACT *)bta_av_a2d_action;
             p_scb->p_cos     = &bta_av_a2d_cos;
             p_scb->media_type= AVDT_MEDIA_AUDIO;
@@ -628,36 +673,128 @@
             if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE)
             {
                 cs.tsep = AVDT_TSEP_SRC;
-                index = 0;
+                startIndex = BTIF_SV_AV_AA_SBC_INDEX;
+                endIndex = BTIF_SV_AV_AA_SRC_SEP_INDEX;
             }
             else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK)
             {
                 cs.tsep = AVDT_TSEP_SNK;
                 cs.p_data_cback = bta_av_stream_data_cback;
-                index = 1;
+                startIndex = BTIF_SV_AV_AA_SBC_SINK_INDEX;
+                endIndex = BTIF_SV_AV_AA_SNK_SEP_INDEX;
             }
 
             /* Initialize Handles to zero */
-            for (int xx=0; xx < BTA_AV_MAX_SEPS; xx++)
+            for(index = 0; index < (endIndex - startIndex); index++)
             {
-                p_scb->seps[xx].av_handle = 0;
+                p_scb->seps[index].av_handle = 0;
             }
 
             /* keep the configuration in the stream control block */
             memcpy(&p_scb->cfg, &cs.cfg, sizeof(tAVDT_CFG));
-            if ((*bta_av_a2d_cos.init)(&codec_type, cs.cfg.codec_info,
-                &cs.cfg.num_protect, cs.cfg.protect_info, index) == TRUE)
+            index = startIndex;
+            while (index < endIndex &&
+                   (*bta_av_a2d_cos.init)(&codec_type, cs.cfg.codec_info,
+                    &cs.cfg.num_protect, cs.cfg.protect_info, index) == TRUE)
             {
-                if(AVDT_CreateStream(&p_scb->seps[index].av_handle, &cs) == AVDT_SUCCESS)
-                {
-                    p_scb->seps[index].codec_type = codec_type;
-                    p_scb->seps[index].tsep = cs.tsep;
-                    if(cs.tsep == AVDT_TSEP_SNK)
-                        p_scb->seps[index].p_app_data_cback = p_data->api_reg.p_app_data_cback;
-                    else
-                        p_scb->seps[index].p_app_data_cback = NULL; /* In case of A2DP SOURCE we don't need a callback to handle media packets */
+                UINT8* ptr = cs.cfg.codec_info;
+                tA2D_APTX_CIE* codecInfo = (tA2D_APTX_CIE*) &ptr[BTA_AV_CFG_START_IDX];
+                UINT32 vendorId = codecInfo->vendorId;
+                UINT16 codecId = codecInfo->codecId;
 
+                if ((*bta_av_a2d_cos.offload)() ==  TRUE)
+                {
+                    if(codec_type == A2D_NON_A2DP_MEDIA_CT)
+                    {
+                       if (vendorId == A2D_APTX_VENDOR_ID &&
+                           codecId == A2D_APTX_CODEC_ID_BLUETOOTH)
+                       {
+                           if((*bta_av_a2d_cos.cap)(APTX) != TRUE)
+                           {
+                               APPL_TRACE_DEBUG("%s: aptx-Classic offload codec not supported",__func__);
+                               index++;
+                               continue;
+                           }
+                           else
+                               APPL_TRACE_DEBUG("%s:aptx-Classic offload codec supported",__func__)
+                       } else {
+                           if (codecId == A2D_APTX_HD_CODEC_ID_BLUETOOTH &&
+                                  vendorId == A2D_APTX_HD_VENDOR_ID ) {
+                               if((*bta_av_a2d_cos.cap)(APTXHD) != TRUE)
+                               {
+                                   APPL_TRACE_DEBUG("%s: aptx-HD offload codec not supported",__func__)
+                                   index++;
+                                   continue;
+                               }
+                               else
+                                   APPL_TRACE_DEBUG("%s: aptx-HD offload codec supported",__func__)
+
+                           }
+                       }
+                    }
+                    else if (codec_type == AAC)
+                    {
+                        if ((*bta_av_a2d_cos.cap)(AAC) != TRUE)
+                        {
+                            APPL_TRACE_DEBUG("%s: AAC offload codec not supported",__func__);
+                            index++;
+                            continue;
+                        } else {
+                            APPL_TRACE_DEBUG("%s: AAC offload codec supported",__func__);
+                        }
+                    }
+                } else if (codec_type == A2D_NON_A2DP_MEDIA_CT) {
+                    if ((codecId == A2D_APTX_CODEC_ID_BLUETOOTH && vendorId == A2D_APTX_VENDOR_ID)
+                        && (A2D_check_and_init_aptX() == false)) {
+                        APPL_TRACE_WARNING("%s aptX not available ", __func__);
+                        index++;
+                        continue;
+
+                    } else {
+                        char value[PROPERTY_VALUE_MAX];
+                        bool enableAptXHD = false;
+                        if (property_get("persist.bt.enableAptXHD", value, "false") && strcmp(value, "true") == 0)
+                            enableAptXHD = true;
+                        else
+                            APPL_TRACE_WARNING("%s enableAptXHD property is not set", __func__);
+
+                        if ((codecId == A2D_APTX_HD_CODEC_ID_BLUETOOTH && vendorId == A2D_APTX_HD_VENDOR_ID) &&
+                            ((enableAptXHD == false) || (A2D_check_and_init_aptX_HD() == false))) {
+                             APPL_TRACE_WARNING("%s aptX-HD not available", __func__);
+                             index++;
+                             continue;
+                        }
+                    }
+                } else if (codec_type == AAC) {
+                    //Don't add AAC in Non split mode
+                    index++;
+                    continue;
                 }
+
+                /* Fix for below klockwork Issues
+                 * Array 'seps' of size 4 may use index value(s) 4 */
+                if (((index - startIndex) < BTA_AV_MAX_SEPS) &&
+                    (AVDT_CreateStream(&p_scb->seps[index - startIndex].av_handle, &cs) ==
+                                                                             AVDT_SUCCESS))
+                {
+                   if ((profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) &&
+                       ((index == BTIF_SV_AV_AA_APTX_INDEX) || (index == BTIF_SV_AV_AA_APTX_HD_INDEX)))
+                   {
+                       p_scb->seps[index - startIndex].vendorId = vendorId;
+                       p_scb->seps[index - startIndex].codecId = codecId;
+                       APPL_TRACE_DEBUG("%s audio[%x] vendorId: %x codecId: %x", __func__,
+                            index, p_scb->seps[index - startIndex].vendorId,
+                            p_scb->seps[index - startIndex].codecId);
+                    }
+                    p_scb->seps[index - startIndex].codec_type = codec_type;
+                    p_scb->seps[index - startIndex].tsep = cs.tsep;
+                    if(cs.tsep == AVDT_TSEP_SNK)
+                        p_scb->seps[index - startIndex].p_app_data_cback = p_data->api_reg.p_app_data_cback;
+                    else
+                        p_scb->seps[index - startIndex].p_app_data_cback = NULL; /* In case of A2DP SOURCE we don't need a callback to handle media packets */
+                    index++;
+                } else
+                    break;
             }
 
             if(!bta_av_cb.reg_audio)
@@ -683,9 +820,10 @@
                     bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SINK);
 #endif
                 }
+
                 /* start listening when A2DP is registered */
                 if (bta_av_cb.features & BTA_AV_FEAT_RCTG)
-                    bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
+                    bta_av_rc_create(&bta_av_cb, AVCT_ACP, p_scb->hdi, BTA_AV_NUM_LINKS + 1);
 
                 /* if the AV and AVK are both supported, it cannot support the CT role */
                 if (bta_av_cb.features & (BTA_AV_FEAT_RCCT))
@@ -709,8 +847,13 @@
                      * because we rely on feature bits being scanned by external
                      * devices more than the profile version itself.
                      */
-                    if ((profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) ||
-                        (profile_initialized == UUID_SERVCLASS_AUDIO_SINK))
+                    if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE)
+                    {
+                        bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL,
+                        p_bta_av_cfg->avrc_ct_cat, BTA_ID_AV,
+                        (bta_av_cb.features & BTA_AV_FEAT_BROWSE), AVRC_REV_1_4);
+                    }
+                    if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK)
                     {
                         bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL,
                         p_bta_av_cfg->avrc_ct_cat, BTA_ID_AV,
@@ -720,7 +863,7 @@
                 }
             }
             bta_av_cb.reg_audio |= BTA_AV_HNDL_TO_MSK(p_scb->hdi);
-            APPL_TRACE_DEBUG("reg_audio: 0x%x",bta_av_cb.reg_audio);
+            APPL_TRACE_DEBUG("reg_audio: 0x%x", bta_av_cb.reg_audio);
         }
         else
         {
@@ -750,6 +893,8 @@
 {
     tBTA_AV_SCB *p_scb = bta_av_hndl_to_scb(p_data->hdr.layer_specific);
 
+    A2D_close_aptX();
+
     if(p_scb)
     {
         p_scb->deregistring = TRUE;
@@ -776,12 +921,12 @@
     tBTA_AV_SCB *p_scb;
     int     i;
     UINT8   chnl = (UINT8)p_data->hdr.layer_specific;
-
     for( i=0; i < BTA_AV_NUM_STRS; i++ )
     {
         p_scb = bta_av_cb.p_scb[i];
-
-        if(p_scb && p_scb->chnl == chnl)
+        //Check if the Stream is in Started state before sending data
+        //in Dual Handoff mode, get SCB where START is done.
+        if(p_scb && (p_scb->chnl == chnl) && (p_scb->started))
         {
             bta_av_ssm_execute(p_scb, BTA_AV_SRC_DATA_READY_EVT, p_data);
         }
@@ -804,6 +949,20 @@
 }
 #endif
 
+BOOLEAN bta_av_multiple_streams_started(void)
+{
+    int xx, stream_count = 0;
+
+    for(xx = 0; xx < BTA_AV_NUM_STRS; xx++)
+    {
+        if((bta_av_cb.p_scb[xx] != NULL) && bta_av_cb.p_scb[xx]->started == TRUE)
+        {
+            stream_count++;
+        }
+    }
+    return (stream_count > 1);
+}
+
 /*******************************************************************************
 **
 ** Function         bta_av_api_to_ssm
@@ -819,10 +978,57 @@
     int xx;
     UINT16 event = p_data->hdr.event - BTA_AV_FIRST_A2S_API_EVT + BTA_AV_FIRST_A2S_SSM_EVT;
 
-    for(xx=0; xx<BTA_AV_NUM_STRS; xx++)
+    /* Multicast: Corner case handling for multicast state getting
+     * updated for ACL connected during the stream start where both
+     * streams are not yet started. We need to take care of this
+     * during suspend to ensure we suspend both streams.
+     */
+    if (is_multicast_enabled == TRUE)
     {
-        bta_av_ssm_execute(bta_av_cb.p_scb[xx], event, p_data);
+        /* Send START request to all Open Stream connections.*/
+        for(xx=0; xx<BTA_AV_NUM_STRS; xx++)
+        {
+            bta_av_ssm_execute(bta_av_cb.p_scb[xx], event, p_data);
+        }
     }
+    else
+    {
+        /*In Dual A2dp Handoff, process this fucntion on specific handles.*/
+        APPL_TRACE_DEBUG("bta_av_api_to_ssm: on Handle 0x%x",p_data->hdr.layer_specific);
+        bta_av_ssm_execute(bta_av_hndl_to_scb(p_data->hdr.layer_specific), event, p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_api_enable_multicast
+**
+** Description      Enable/Disable Avdtp multicast
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_api_enable_multicast(tBTA_AV_DATA *p_data)
+{
+    is_multicast_enabled = p_data->multicast_state.is_multicast_enabled;
+    APPL_TRACE_DEBUG("is_multicast_enabled :%d", is_multicast_enabled);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_api_update_max_av_client
+**
+** Description      Update max simultaneous AV connections supported
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_api_update_max_av_clients(tBTA_AV_DATA *p_data)
+{
+    int bta_av_max_clients = p_data->max_av_clients.max_clients;
+    APPL_TRACE_DEBUG("bta_av_max_clients:%d",bta_av_max_clients);
+    AVDT_UpdateMaxAvClients(bta_av_max_clients);
 }
 
 /*******************************************************************************
@@ -840,7 +1046,7 @@
     BOOLEAN start = FALSE;
     tBTA_AV_SCB *p_scbi;
     int i;
-
+    APPL_TRACE_DEBUG("bta_av_chk_start: Audio open count: 0x%x",bta_av_cb.audio_open_cnt);
     if(p_scb->chnl == BTA_AV_CHNL_AUDIO)
     {
         if ((bta_av_cb.audio_open_cnt >= 2) &&
@@ -854,7 +1060,16 @@
                 p_scbi = bta_av_cb.p_scb[i];
                 if(p_scbi && p_scbi->chnl == BTA_AV_CHNL_AUDIO && p_scbi->co_started)
                 {
-                    start = TRUE;
+                    if (is_multicast_enabled == TRUE)
+                    {
+                        start = TRUE;
+                    }
+                    else
+                    {
+                        start = FALSE;
+                        APPL_TRACE_DEBUG("bta_av_chk_start: Already playing");
+                        break;
+                    }
                     /* may need to update the flush timeout of this already started stream */
                     if(p_scbi->co_started != bta_av_cb.audio_open_cnt)
                     {
@@ -962,11 +1177,17 @@
         {
             APPL_TRACE_DEBUG ("bta_av_sys_rs_cback: rs_idx(%d), hndl:x%x q_tag: %d",
                 bta_av_cb.rs_idx, p_scb->hndl, p_scb->q_tag);
-
+            /* Multicast:
+             * As per Multicast feature implementation, fallback
+             * happens to soft hand-off when DUT is in scatternet
+             * scenario. Hence, don't fail the connection if
+             * role switch fails because of remote disallowing.
+             * Set switch_res to BTA_AV_RS_DONE on failure.
+             */
             if(HCI_SUCCESS == app_id || HCI_ERR_NO_CONNECTION == app_id)
                 p_scb->q_info.open.switch_res = BTA_AV_RS_OK;
             else
-                p_scb->q_info.open.switch_res = BTA_AV_RS_FAIL;
+                p_scb->q_info.open.switch_res = BTA_AV_RS_DONE;
 
             /* Continue av open process */
             bta_av_do_disc_a2d (p_scb, (tBTA_AV_DATA *)&(p_scb->q_info.open));
@@ -1050,6 +1271,7 @@
     UINT8 role;
     BOOLEAN needed = FALSE;
     tBTA_AV_SCB *p_scbi;
+    tBTM_STATUS ret;
     int i;
     UINT8       mask;
 
@@ -1067,7 +1289,12 @@
             {
                 if (bta_av_cb.features & BTA_AV_FEAT_MASTER)
                     bta_sys_clear_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_scbi->peer_addr);
-                if (BTM_CMD_STARTED != BTM_SwitchRole(p_scbi->peer_addr, BTM_ROLE_MASTER, NULL))
+                ret = BTM_SwitchRole(p_scbi->peer_addr, BTM_ROLE_MASTER, NULL);
+                if ((ret == BTM_REPEATED_ATTEMPTS) ||
+                   ((ret == BTM_NO_RESOURCES) && btm_is_sco_active_by_bdaddr(p_scbi->peer_addr)))
+                    return FALSE;
+
+                if (BTM_CMD_STARTED != ret)
                 {
                     /* can not switch role on SCBI
                      * start the timer on SCB - because this function is ONLY called when SCB gets API_OPEN */
@@ -1099,18 +1326,27 @@
 {
     UINT8 role;
     BOOLEAN is_ok = TRUE;
+    tBTM_STATUS ret;
 
     if (BTM_GetRole(p_scb->peer_addr, &role) == BTM_SUCCESS)
     {
-        LOG_INFO(LOG_TAG, "%s hndl:x%x role:%d conn_audio:x%x bits:%d features:x%x",
+        LOG_INFO("%s hndl:x%x role:%d conn_audio:x%x bits:%d features:x%x",
                 __func__, p_scb->hndl, role, bta_av_cb.conn_audio, bits,
                 bta_av_cb.features);
         if (BTM_ROLE_MASTER != role && (A2D_BitsSet(bta_av_cb.conn_audio) > bits || (bta_av_cb.features & BTA_AV_FEAT_MASTER)))
         {
             if (bta_av_cb.features & BTA_AV_FEAT_MASTER)
                 bta_sys_clear_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_scb->peer_addr);
+            ret = BTM_SwitchRole(p_scb->peer_addr, BTM_ROLE_MASTER, NULL);
+            /* We have already reached maximum attempts,
+             * If we try again it will anyways fail
+             * return from here
+             * */
+            if ((ret == BTM_REPEATED_ATTEMPTS) ||
+                ((ret == BTM_NO_RESOURCES) && btm_is_sco_active_by_bdaddr(p_scb->peer_addr)))
+                return TRUE;
 
-            if (BTM_CMD_STARTED != BTM_SwitchRole(p_scb->peer_addr, BTM_ROLE_MASTER, NULL))
+            if (BTM_CMD_STARTED != ret)
             {
                 /* can not switch role on SCB - start the timer on SCB */
             }
@@ -1276,6 +1512,7 @@
         APPL_TRACE_VERBOSE("AV nsm event=0x%x", event);
 #endif
         /* non state machine events */
+
         (*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT]) ((tBTA_AV_DATA *) p_msg);
     }
     else if (event >= BTA_AV_FIRST_SM_EVT && event <= BTA_AV_LAST_SM_EVT)
@@ -1298,6 +1535,20 @@
     return TRUE;
 }
 
+/*******************************************************************************
+**
+** Function         bta_av_is_multicast_enabled
+**
+** Description      return status of Avdtp multicast
+**
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+BOOLEAN bta_av_is_multicast_enabled()
+{
+    return is_multicast_enabled;
+}
 /*****************************************************************************
 **  Debug Functions
 *****************************************************************************/
@@ -1397,6 +1648,7 @@
 #endif
     case BTA_AV_API_START_EVT: return "API_START";
     case BTA_AV_API_STOP_EVT: return "API_STOP";
+    case BTA_AV_ENABLE_MULTICAST_EVT: return "MULTICAST_ENABLE";
     default:             return "unknown";
     }
 }
diff --git a/bta/av/bta_av_ssm.c b/bta/av/bta_av_ssm.c
index 6ad8bcd..71f508c 100644
--- a/bta/av/bta_av_ssm.c
+++ b/bta/av/bta_av_ssm.c
@@ -172,7 +172,7 @@
 /* STR_DISC_OK_EVT */       {BTA_AV_DISC_RES_AS_ACP,BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
 /* STR_DISC_FAIL_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
 /* STR_GETCAP_OK_EVT */     {BTA_AV_SAVE_CAPS,      BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
-/* STR_GETCAP_FAIL_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_GETCAP_FAIL_EVT */   {BTA_AV_OPEN_FAILED,    BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
 /* STR_OPEN_OK_EVT */       {BTA_AV_STR_OPENED,     BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
 /* STR_OPEN_FAIL_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
 /* STR_START_OK_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
@@ -186,7 +186,7 @@
 /* STR_RECONFIG_CFM_EVT */  {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
 /* AVRC_TIMER_EVT */        {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
 /* AVDT_CONNECT_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
-/* AVDT_DISCONNECT_EVT */   {BTA_AV_CCO_CLOSE,      BTA_AV_DISCONNECT_REQ, BTA_AV_CLOSING_SST },
+/* AVDT_DISCONNECT_EVT */   {BTA_AV_CCO_CLOSE,      BTA_AV_CLEANUP,        BTA_AV_INIT_SST},
 /* ROLE_CHANGE_EVT*/        {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
 /* AVDT_DELAY_RPT_EVT */    {BTA_AV_DELAY_CO,       BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
 /* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
@@ -210,7 +210,7 @@
 /* CI_SETCONFIG_OK_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
 /* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
 /* SDP_DISC_OK_EVT */       {BTA_AV_CONNECT_REQ,    BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
-/* SDP_DISC_FAIL_EVT */     {BTA_AV_CONNECT_REQ,    BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* SDP_DISC_FAIL_EVT */     {BTA_AV_SDP_FAILED,     BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
 /* STR_DISC_OK_EVT */       {BTA_AV_DISC_RESULTS,   BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
 /* STR_DISC_FAIL_EVT */     {BTA_AV_OPEN_FAILED,    BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
 /* STR_GETCAP_OK_EVT */     {BTA_AV_GETCAP_RESULTS, BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
@@ -449,18 +449,58 @@
         }
     }
 
-#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
-    APPL_TRACE_VERBOSE("AV Sevent(0x%x)=0x%x(%s) state=%d(%s)",
-        p_scb->hndl, event, bta_av_evt_code(event), p_scb->state, bta_av_sst_code(p_scb->state));
-#else
-    APPL_TRACE_VERBOSE("AV Sevent=0x%x state=%d", event, p_scb->state);
-#endif
+    if ((event != BTA_AV_STR_WRITE_CFM_EVT) && (event != BTA_AV_SRC_DATA_READY_EVT))
+    {
+        #if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+            APPL_TRACE_IMP("AV Sevent(0x%x)=0x%x(%s) state=%d(%s)",
+               p_scb->hndl, event, bta_av_evt_code(event), p_scb->state, bta_av_sst_code(p_scb->state));
+        #else
+            APPL_TRACE_IMP("AV Sevent=0x%x state=%d", event, p_scb->state);
+        #endif
+    }
 
     /* look up the state table for the current state */
     state_table = bta_av_sst_tbl[p_scb->state];
 
     event -= BTA_AV_FIRST_SSM_EVT;
 
+    if((p_scb->state != BTA_AV_OPENING_SST) &&
+        (state_table[event][BTA_AV_SNEXT_STATE] == BTA_AV_OPENING_SST))
+    {
+        AVDT_UpdateServiceBusyState(TRUE);
+    }
+    else if(AVDT_GetServiceBusyState() == TRUE)
+    {
+        BOOLEAN keep_busy = TRUE;
+
+        for (xx = 0; xx < BTA_AV_NUM_STRS; xx++)
+        {
+            if (bta_av_cb.p_scb[xx])
+            {
+                if ((bta_av_cb.p_scb[xx]->state == BTA_AV_OPENING_SST) &&
+                    (bta_av_cb.p_scb[xx] != p_scb))
+                {
+                    /* There is other SCB in opening state
+                     * keep the service state in progress
+                     */
+                    APPL_TRACE_VERBOSE("SCB in opening state. Keep Busy");
+                    keep_busy = TRUE;
+                    break;
+                }
+                else if ((bta_av_cb.p_scb[xx]->state == BTA_AV_OPENING_SST) &&
+                    (bta_av_cb.p_scb[xx] == p_scb) &&
+                    (state_table[event][BTA_AV_SNEXT_STATE] != BTA_AV_OPENING_SST))
+                {
+                    keep_busy = FALSE;
+                }
+            }
+        }
+        if (keep_busy == FALSE)
+        {
+            AVDT_UpdateServiceBusyState(FALSE);
+        }
+    }
+
     /* set next state */
     p_scb->state = state_table[event][BTA_AV_SNEXT_STATE];
 
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index e361970..0b71da2 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -45,6 +45,7 @@
 #include "osi/include/osi.h"
 #include "sdp_api.h"
 #include "utl.h"
+#include "device/include/interop_config.h"
 
 #if (GAP_INCLUDED == TRUE)
 #include "gap_api.h"
@@ -106,6 +107,8 @@
 static void bta_dm_ctrl_features_rd_cmpl_cback(tBTM_STATUS result);
 #endif
 
+static void bta_dm_ext_adv_ctrl_features_rd_cmpl_cback(tBTM_STATUS result);
+
 #ifndef BTA_DM_BLE_ADV_CHNL_MAP
 #define BTA_DM_BLE_ADV_CHNL_MAP (BTM_BLE_ADV_CHNL_37|BTM_BLE_ADV_CHNL_38|BTM_BLE_ADV_CHNL_39)
 #endif
@@ -306,17 +309,6 @@
 *******************************************************************************/
 void bta_dm_init_cb(void)
 {
-    /*
-     * TODO: Should alarm_free() the bta_dm_cb timers during graceful
-     * shutdown.
-     */
-    alarm_free(bta_dm_cb.disable_timer);
-    alarm_free(bta_dm_cb.switch_delay_timer);
-    for (size_t i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
-        for (size_t j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) {
-            alarm_free(bta_dm_cb.pm_timer[i].timer[j]);
-        }
-    }
     memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));
     bta_dm_cb.disable_timer = alarm_new("bta_dm.disable_timer");
     bta_dm_cb.switch_delay_timer = alarm_new("bta_dm.switch_delay_timer");
@@ -329,6 +321,32 @@
 
 /*******************************************************************************
 **
+** Function         bta_dm_deinit_cb
+**
+** Description      De-initializes the bta_dm_cb control block
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_deinit_cb(void)
+{
+    /*
+     * TODO: Should alarm_free() the bta_dm_cb timers during graceful
+     * shutdown.
+     */
+    alarm_free(bta_dm_cb.disable_timer);
+    alarm_free(bta_dm_cb.switch_delay_timer);
+    for (size_t i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
+      for (size_t j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) {
+        alarm_free(bta_dm_cb.pm_timer[i].timer[j]);
+      }
+    }
+    memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));
+}
+
+/*******************************************************************************
+**
 ** Function         bta_dm_sys_hw_cback
 **
 ** Description     callback register to SYS to get HW status updates
@@ -362,7 +380,12 @@
             bta_dm_cb.p_sec_cback(BTA_DM_DISABLE_EVT, NULL);
 
         /* reinitialize the control block */
-        bta_dm_init_cb();
+        bta_dm_deinit_cb();
+
+        /* hw is ready, go on with BTA DM initialization */
+        alarm_free(bta_dm_search_cb.search_timer);
+        alarm_free(bta_dm_search_cb.gatt_close_timer);
+        memset(&bta_dm_search_cb, 0, sizeof(bta_dm_search_cb));
 
         /* unregister from SYS */
         bta_sys_hw_unregister( BTA_SYS_HW_BLUETOOTH );
@@ -385,8 +408,6 @@
         bta_dm_cb.is_bta_dm_active = TRUE;
 
         /* hw is ready, go on with BTA DM initialization */
-        alarm_free(bta_dm_search_cb.search_timer);
-        alarm_free(bta_dm_search_cb.gatt_close_timer);
         memset(&bta_dm_search_cb, 0, sizeof(bta_dm_search_cb));
         /*
          * TODO: Should alarm_free() the bta_dm_search_cb timers during
@@ -431,6 +452,9 @@
         BTM_BleReadControllerFeatures (bta_dm_ctrl_features_rd_cmpl_cback);
 #endif
 
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+        BTM_BleReadExtAdvControllerFeatures (bta_dm_ext_adv_ctrl_features_rd_cmpl_cback);
+#endif
         /* Earlier, we used to invoke BTM_ReadLocalAddr which was just copying the bd_addr
            from the control block and invoking the callback which was sending the DM_ENABLE_EVT.
            But then we have a few HCI commands being invoked above which were still in progress
@@ -469,6 +493,7 @@
 void bta_dm_disable (tBTA_DM_MSG *p_data)
 {
     UNUSED(p_data);
+    int soc_type = get_soc_type();
 
     /* Set l2cap idle timeout to 0 (so BTE immediately disconnects ACL link after last channel is closed) */
     L2CA_SetIdleTimeoutByBdAddr((UINT8 *)BT_BD_ANY, 0, BT_TRANSPORT_BR_EDR);
@@ -488,6 +513,18 @@
     BTM_BleClearBgConnDev();
 #endif
 
+    /* Disable SOC Logging */
+    if (soc_type == BT_SOC_SMD)
+    {
+        UINT8       param[5] = {0x10, 0x02, 0x00, 0x00, 0x01};
+        BTM_VendorSpecificCommand(HCI_VS_HOST_LOG_OPCODE, 5, param, NULL);
+    }
+    else if (soc_type == BT_SOC_CHEROKEE)
+    {
+        UINT8       param_cherokee[2] = {0x14, 0x00};
+        BTM_VendorSpecificCommand(HCI_VS_HOST_LOG_OPCODE, 2, param_cherokee, NULL);
+    }
+
     if(BTM_GetNumAclLinks()==0)
     {
 #if (defined(BTA_DISABLE_DELAY) && BTA_DISABLE_DELAY > 0)
@@ -558,7 +595,7 @@
         bta_dm_cb.disabling = FALSE;
 
         bta_sys_remove_uuid(UUID_SERVCLASS_PNP_INFORMATION);
-        bta_dm_cb.p_sec_cback(BTA_DM_DISABLE_EVT, NULL);
+        bta_dm_disable_conn_down_timer_cback(NULL);
     }
 }
 
@@ -665,7 +702,47 @@
 
 /*******************************************************************************
 **
-** Function         bta_dm_process_remove_device
+** Function         bta_dm_hci_raw_command
+**
+** Description      Send a HCI RAW command to the controller
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_hci_raw_command (tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS status;
+    APPL_TRACE_API("bta_dm_hci_raw_command");
+    status = BTM_Hci_Raw_Command(p_data->btc_command.opcode,p_data->btc_command.param_len,p_data->btc_command.p_param_buf, p_data->btc_command.p_cback);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_vendor_spec_command
+**
+** Description      Send a vendor specific command to the controller
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_vendor_spec_command (tBTA_DM_MSG *p_data)
+{
+    APPL_TRACE_API("bta_dm_vendor_spec_command");
+    BTM_VendorSpecificCommand(p_data->vendor_command.opcode,
+                                       p_data->vendor_command.param_len,
+                                       p_data->vendor_command.p_param_buf,
+                                       p_data->vendor_command.p_cback);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_process_remove_deviced
+**
+**
+** Returns          void
 **
 ** Description      Removes device, Disconnects ACL link if required.
 ****
@@ -712,8 +789,11 @@
     bdcpy(other_address, p_dev->bd_addr);
 
     /* If ACL exists for the device in the remove_bond message*/
+    bt_bdaddr_t remote_bdaddr;
+    bdcpy(remote_bdaddr.address, p_dev->bd_addr);
     BOOLEAN continue_delete_dev = FALSE;
     UINT8 other_transport = BT_TRANSPORT_INVALID;
+    interop_database_remove_addr(INTEROP_DYNAMIC_ROLE_SWITCH, (bt_bdaddr_t *)&remote_bdaddr);
 
     if (BTM_IsAclConnectionUp(p_dev->bd_addr, BT_TRANSPORT_LE) ||
         BTM_IsAclConnectionUp(p_dev->bd_addr, BT_TRANSPORT_BR_EDR))
@@ -763,9 +843,13 @@
         /* Take the link down first, and mark the device for removal when disconnected */
         for(int i=0; i < bta_dm_cb.device_list.count; i++)
         {
-            if (!bdcmp(bta_dm_cb.device_list.peer_device[i].peer_bdaddr, other_address))
+            if ((!bdcmp(bta_dm_cb.device_list.peer_device[i].peer_bdaddr, other_address))&&
+               ((other_transport && (other_transport == bta_dm_cb.device_list.peer_device[i].transport)) ||
+               !other_transport))
             {
                 bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_UNPAIRING;
+                APPL_TRACE_DEBUG("%s:transport = %d ,other_transport = %d", __func__,
+                                  bta_dm_cb.device_list.peer_device[i].transport, other_transport);
                 btm_remove_acl(other_address,bta_dm_cb.device_list.peer_device[i].transport);
                 break;
             }
@@ -2185,6 +2269,8 @@
     /* no more services to be discovered */
     if (bta_dm_search_cb.service_index >= BTA_MAX_SERVICE_ID) {
         tBTA_DM_MSG *p_msg = (tBTA_DM_MSG *)osi_malloc(sizeof(tBTA_DM_MSG));
+        /* initialize the data structure - includes p_raw_data and raw_data_size */
+        memset(&(p_msg->disc_result.result), 0, sizeof(tBTA_DM_DISC_RES));
         p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
         p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
         bdcpy(p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
@@ -2323,10 +2409,12 @@
             /* check whether connection already exists to the device
                if connection exists, we don't have to wait for ACL
                link to go down to start search on next device */
-            if (BTM_IsAclConnectionUp(bta_dm_search_cb.peer_bdaddr, BT_TRANSPORT_BR_EDR))
-                bta_dm_search_cb.wait_disc = FALSE;
-            else
-                bta_dm_search_cb.wait_disc = TRUE;
+            if (transport == BT_TRANSPORT_BR_EDR) {
+                if (BTM_IsAclConnectionUp(bta_dm_search_cb.peer_bdaddr, BT_TRANSPORT_BR_EDR))
+                    bta_dm_search_cb.wait_disc = FALSE;
+                else
+                    bta_dm_search_cb.wait_disc = TRUE;
+            }
 
 #if (BLE_INCLUDED == TRUE && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
             if ( bta_dm_search_cb.p_btm_inq_info )
@@ -2427,6 +2515,7 @@
     result.inq_res.device_type      = p_inq->device_type;
     result.inq_res.flag             = p_inq->flag;
 #endif
+    result.inq_res.adv_data_len     = p_inq->adv_data_len;
 
     /* application will parse EIR to find out remote device name */
     result.inq_res.p_eir = p_eir;
@@ -2670,6 +2759,12 @@
 
         /* 1 additional event data fields for this event */
         sec_event.cfm_req.just_works = bta_dm_cb.just_works;
+        /* retrieve the loc and rmt caps */
+        sec_event.cfm_req.loc_io_caps = bta_dm_cb.loc_io_caps;
+        sec_event.cfm_req.rmt_io_caps = bta_dm_cb.rmt_io_caps;
+        sec_event.cfm_req.loc_auth_req = bta_dm_cb.loc_auth_req;
+        sec_event.cfm_req.rmt_auth_req = bta_dm_cb.rmt_auth_req;
+
     }
     else
     {
@@ -2881,16 +2976,21 @@
     /*case BTM_SP_KEY_REQ_EVT: */
     case BTM_SP_KEY_NOTIF_EVT:
 #endif
-        bta_dm_cb.num_val = sec_event.key_notif.passkey = p_data->key_notif.passkey;
 
         if(BTM_SP_CFM_REQ_EVT == event)
         {
+          bta_dm_cb.num_val = sec_event.key_notif.passkey = p_data->cfm_req.num_val;
           /* Due to the switch case falling through below to BTM_SP_KEY_NOTIF_EVT,
              call remote name request using values from cfm_req */
           if(p_data->cfm_req.bd_name[0] == 0)
           {
               bta_dm_cb.pin_evt = pin_evt;
               bdcpy(bta_dm_cb.pin_bd_addr, p_data->cfm_req.bd_addr);
+              bta_dm_cb.rmt_io_caps = sec_event.cfm_req.rmt_io_caps;
+              bta_dm_cb.loc_io_caps = sec_event.cfm_req.loc_io_caps;
+              bta_dm_cb.rmt_auth_req = sec_event.cfm_req.rmt_auth_req;
+              bta_dm_cb.loc_auth_req = sec_event.cfm_req.loc_auth_req;
+
               BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->cfm_req.dev_class);
               if ((BTM_ReadRemoteDeviceName(p_data->cfm_req.bd_addr, bta_dm_pinname_cback,
                          BT_TRANSPORT_BR_EDR)) == BTM_CMD_STARTED)
@@ -2910,11 +3010,16 @@
 
         if (BTM_SP_KEY_NOTIF_EVT == event)
         {
+
+            bta_dm_cb.num_val = sec_event.key_notif.passkey = p_data->key_notif.passkey;
             /* If the device name is not known, save bdaddr and devclass
                and initiate a name request with values from key_notif */
             if(p_data->key_notif.bd_name[0] == 0)
             {
                 bta_dm_cb.pin_evt = pin_evt;
+                /* Store the local and remote io caps */
+                bta_dm_cb.loc_io_caps = sec_event.cfm_req.loc_io_caps;
+                bta_dm_cb.rmt_io_caps = sec_event.cfm_req.rmt_io_caps;
                 bdcpy(bta_dm_cb.pin_bd_addr, p_data->key_notif.bd_addr);
                 BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->key_notif.dev_class);
                 if ((BTM_ReadRemoteDeviceName(p_data->key_notif.bd_addr, bta_dm_pinname_cback,
@@ -3236,9 +3341,12 @@
         {
             if (bta_dm_cb.device_list.count < BTA_DM_NUM_PEER_DEVICE)
             {
+                /* new acl connection,reset new peer device */
+                memset(&bta_dm_cb.device_list.peer_device[i], 0, sizeof(bta_dm_cb.device_list.peer_device[i]));
                 bdcpy(bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count].peer_bdaddr, p_bda);
                 bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count].link_policy = bta_dm_cb.cur_policy;
                 bta_dm_cb.device_list.count++;
+                APPL_TRACE_ERROR("%s new acl connetion:count = %d", __func__, bta_dm_cb.device_list.count);
 #if BLE_INCLUDED == TRUE
                 bta_dm_cb.device_list.peer_device[i].conn_handle = p_data->acl_change.handle;
                 if (p_data->acl_change.transport == BT_TRANSPORT_LE)
@@ -3289,10 +3397,12 @@
 
             conn.link_down.is_removed = bta_dm_cb.device_list.peer_device[i].remove_dev_pending;
 
-            for(; i<bta_dm_cb.device_list.count ; i++)
+            /* acl disconnection,remove peer device entry and reset last entry */
+            for(; i < (bta_dm_cb.device_list.count - 1); i++)
             {
                 memcpy(&bta_dm_cb.device_list.peer_device[i], &bta_dm_cb.device_list.peer_device[i+1], sizeof(bta_dm_cb.device_list.peer_device[i]));
             }
+            memset(&bta_dm_cb.device_list.peer_device[i], 0, sizeof(bta_dm_cb.device_list.peer_device[i]));
             break;
         }
         if(bta_dm_cb.device_list.count)
@@ -3304,7 +3414,8 @@
         conn.link_down.link_type = p_data->acl_change.transport;
 #endif
 
-        if(bta_dm_search_cb.wait_disc && !bdcmp(bta_dm_search_cb.peer_bdaddr, p_bda))
+        if ((p_data->acl_change.transport == BT_TRANSPORT_BR_EDR) &&
+             bta_dm_search_cb.wait_disc && !bdcmp(bta_dm_search_cb.peer_bdaddr, p_bda))
         {
             bta_dm_search_cb.wait_disc = FALSE;
 
@@ -4269,7 +4380,6 @@
 ;
     tBTA_DM_SEARCH     result;
     tBTM_INQ_INFO      *p_inq_info;
-    APPL_TRACE_DEBUG("bta_dm_observe_results_cb")
 
     bdcpy(result.inq_res.bd_addr, p_inq->remote_bd_addr);
     result.inq_res.rssi = p_inq->rssi;
@@ -4277,6 +4387,7 @@
     result.inq_res.inq_result_type  = p_inq->inq_result_type;
     result.inq_res.device_type      = p_inq->device_type;
     result.inq_res.flag             = p_inq->flag;
+    result.inq_res.adv_data_len     = p_inq->adv_data_len;
 
     /* application will parse EIR to find out remote device name */
     result.inq_res.p_eir = p_eir;
@@ -4393,7 +4504,11 @@
 
         case BTM_LE_NC_REQ_EVT:
             bdcpy(sec_event.key_notif.bd_addr, bda);
-            strlcpy((char*)sec_event.key_notif.bd_name, bta_dm_get_remname(), (BD_NAME_LEN));
+            char* bd_name = BTM_SecReadDevName(bda);
+            if (bd_name)
+                strlcpy((char*)sec_event.key_notif.bd_name, bd_name, (BD_NAME_LEN));
+            else
+                strlcpy((char*)sec_event.key_notif.bd_name, bta_dm_get_remname(), (BD_NAME_LEN));
             sec_event.key_notif.passkey = p_data->key_notif;
             bta_dm_cb.p_sec_cback(BTA_DM_BLE_NC_REQ_EVT, &sec_event);
             break;
@@ -4430,8 +4545,7 @@
             else
             {
                 sec_event.auth_cmpl.success = TRUE;
-                if (!p_data->complt.smp_over_br)
-                    GATT_ConfigServiceChangeCCC(bda, TRUE, BT_TRANSPORT_LE);
+                sec_event.auth_cmpl.smp_over_br = p_data->complt.smp_over_br;
             }
 
             if (bta_dm_cb.p_sec_cback)
@@ -4640,8 +4754,11 @@
 void bta_dm_ble_set_scan_params(tBTA_DM_MSG *p_data)
 {
     BTM_BleSetScanParams(p_data->ble_set_scan_params.client_if,
+                         p_data->ble_set_scan_params.scan_phys,
                          p_data->ble_set_scan_params.scan_int,
                          p_data->ble_set_scan_params.scan_window,
+                         p_data->ble_set_scan_params.scan_int_coded,
+                         p_data->ble_set_scan_params.scan_window_coded,
                          p_data->ble_set_scan_params.scan_mode,
                          p_data->ble_set_scan_params.scan_param_setup_cback);
 }
@@ -4714,6 +4831,7 @@
         /*Save the  callback to be called when a scan results are available */
         bta_dm_search_cb.p_scan_cback = p_data->ble_observe.p_cback;
         if ((status = BTM_BleObserve(TRUE, p_data->ble_observe.duration,
+                            p_data->ble_observe.period,
                             bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb))!= BTM_CMD_STARTED)
         {
             tBTA_DM_SEARCH  data;
@@ -4728,7 +4846,7 @@
     else
     {
         bta_dm_search_cb.p_scan_cback = NULL;
-        BTM_BleObserve(FALSE, 0, NULL,NULL );
+        BTM_BleObserve(FALSE, 0, p_data->ble_observe.period, NULL, NULL );
     }
 }
 /*******************************************************************************
@@ -4814,6 +4932,43 @@
 
 /*******************************************************************************
 **
+** Function         bta_dm_ble_set_phy
+**
+** Description      This function sets the tx and rx phy for a connection
+**
+** Parameters
+**
+*******************************************************************************/
+void bta_dm_ble_set_phy(tBTA_DM_MSG *p_data)
+{
+    if (BTM_SetBlePhy(p_data->ble_set_phy.remote_bda, p_data->ble_set_phy.all_phy,
+                      p_data->ble_set_phy.tx_phy, p_data->ble_set_phy.rx_phy,
+                      p_data->ble_set_phy.phy_options) != BTM_SUCCESS)
+    {
+        APPL_TRACE_ERROR("%s failed", __func__);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_set_default_phy
+**
+** Description      This function sets the default tx and rx phy
+**
+** Parameters
+**
+*******************************************************************************/
+void bta_dm_ble_set_default_phy(tBTA_DM_MSG *p_data)
+{
+    if (BTM_SetDefaultBlePhy(p_data->ble_set_default_phy.all_phy,
+                      p_data->ble_set_default_phy.tx_phy, p_data->ble_set_default_phy.rx_phy) != BTM_SUCCESS)
+    {
+        APPL_TRACE_ERROR("%s failed", __func__);
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         bta_dm_ble_broadcast
 **
 ** Description      Starts or stops LE broadcasts
@@ -4903,6 +5058,7 @@
         btm_status = BTM_BleCfgAdvInstData(p_data->ble_multi_adv_data.inst_id,
                         p_data->ble_multi_adv_data.is_scan_rsp,
                         p_data->ble_multi_adv_data.data_mask,
+                        p_data->ble_multi_adv_data.frag_pref,
                         (tBTM_BLE_ADV_DATA*)&p_data->ble_multi_adv_data.data);
     }
 
@@ -5316,7 +5472,7 @@
 
 #if ((defined BTA_GATT_INCLUDED) &&  (BTA_GATT_INCLUDED == TRUE))
 #ifndef BTA_DM_GATT_CLOSE_DELAY_TOUT
-#define BTA_DM_GATT_CLOSE_DELAY_TOUT    1000
+#define BTA_DM_GATT_CLOSE_DELAY_TOUT    5000
 #endif
 
 /*******************************************************************************
@@ -5667,5 +5823,28 @@
 
 }
 #endif /* BLE_VND_INCLUDED */
+/*******************************************************************************
+**
+** Function         bta_dm_ext_adv_ctrl_features_rd_cmpl_cback
+**
+** Description      callback to handle controller feature read complete
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_dm_ext_adv_ctrl_features_rd_cmpl_cback(tBTM_STATUS result)
+{
+    APPL_TRACE_DEBUG("%s  status = %d ", __FUNCTION__, result);
+    if (result == BTM_SUCCESS)
+    {
+        if(bta_dm_cb.p_sec_cback)
+            bta_dm_cb.p_sec_cback(BTA_DM_LE_ADV_EXT_FEATURES_READ, NULL);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("%s Ctrl BLE ADV EXT feature read failed: status :%d",__FUNCTION__, result);
+    }
+
+}
 
 #endif  /* BLE_INCLUDED */
diff --git a/bta/dm/bta_dm_api.c b/bta/dm/bta_dm_api.c
index 82dd8b2..42167ae 100644
--- a/bta/dm/bta_dm_api.c
+++ b/bta/dm/bta_dm_api.c
@@ -65,8 +65,6 @@
     if (bta_dm_cb.disabling)
         return BTA_FAILURE;
 
-    bta_dm_init_cb();
-
     bta_sys_register(BTA_ID_DM, &bta_dm_reg );
     bta_sys_register(BTA_ID_DM_SEARCH, &bta_dm_search_reg );
 
@@ -194,6 +192,95 @@
 
 /*******************************************************************************
 **
+** Function         BTA_DmHciRawCommand
+**
+** Description      This function sends the HCI Raw  command
+**                  to the controller
+**
+**
+** Returns          tBTA_STATUS
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmHciRawCommand (UINT16 opcode, UINT8 param_len,
+                                         UINT8 *p_param_buf,
+                                         tBTA_RAW_CMPL_CBACK *p_cback)
+{
+
+    tBTA_DM_API_RAW_COMMAND    *p_msg;
+    UINT16 size;
+
+    size = sizeof (tBTA_DM_API_RAW_COMMAND) + param_len;
+    p_msg = (tBTA_DM_API_RAW_COMMAND *) osi_malloc(size);
+    if (p_msg != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_HCI_RAW_COMMAND_EVT;
+        p_msg->opcode = opcode;
+        p_msg->param_len = param_len;
+        p_msg->p_param_buf = (UINT8 *)(p_msg + 1);
+        p_msg->p_cback = p_cback;
+
+        memcpy (p_msg->p_param_buf, p_param_buf, param_len);
+
+        bta_sys_sendmsg(p_msg);
+    }
+    return BTA_SUCCESS;
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmVendorSpecificCommand
+**
+** Description      This function sends the vendor specific command
+**                  to the controller
+**
+**
+** Returns          tBTA_STATUS
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmVendorSpecificCommand (UINT16 opcode, UINT8 param_len,
+                                         UINT8 *p_param_buf,
+                                         tBTA_VENDOR_CMPL_CBACK *p_cback)
+{
+
+    tBTA_DM_API_VENDOR_SPECIFIC_COMMAND    *p_msg;
+    UINT16 size;
+
+    /* If p_cback is NULL, Notify application */
+    if (p_cback == NULL)
+    {
+        return (BTA_FAILURE);
+    }
+    else
+    {
+        size = sizeof (tBTA_DM_API_VENDOR_SPECIFIC_COMMAND) + param_len;
+        if ((p_msg = (tBTA_DM_API_VENDOR_SPECIFIC_COMMAND *) osi_malloc(size)) != NULL)
+        {
+            p_msg->hdr.event = BTA_DM_API_VENDOR_SPECIFIC_COMMAND_EVT;
+            p_msg->opcode = opcode;
+            p_msg->p_param_buf = (UINT8 *)(p_msg + 1);
+            p_msg->p_cback = p_cback;
+
+            if (p_param_buf && param_len)
+            {
+                memcpy (p_msg->p_param_buf, p_param_buf, param_len);
+                p_msg->param_len = param_len;
+            }
+            else
+            {
+                p_msg->param_len = 0;
+                p_msg->p_param_buf = NULL;
+
+            }
+
+            bta_sys_sendmsg(p_msg);
+        }
+        return (BTA_SUCCESS);
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         BTA_DmSearch
 **
 ** Description      This function searches for peer Bluetooth devices. It performs
@@ -847,10 +934,10 @@
 ** Returns          void
 **
 *******************************************************************************/
-
 #if BLE_INCLUDED == TRUE
-void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval,
-                            UINT32 scan_window, tBLE_SCAN_MODE scan_mode,
+void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT8 scan_phys, UINT32 scan_interval,
+                            UINT32 scan_window, UINT16 scan_interval_coded,
+                            UINT16 scan_window_coded, tBLE_SCAN_MODE scan_mode,
                             tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback)
 {
     tBTA_DM_API_BLE_SCAN_PARAMS *p_msg =
@@ -858,11 +945,14 @@
 
     p_msg->hdr.event = BTA_DM_API_BLE_SCAN_PARAM_EVT;
     p_msg->client_if = client_if;
+    p_msg->scan_phys = scan_phys;
     p_msg->scan_int = scan_interval;
     p_msg->scan_window = scan_window;
+    p_msg->scan_int_coded = scan_interval_coded;
+    p_msg->scan_window_coded = scan_window_coded;
+
     p_msg->scan_mode = scan_mode;
     p_msg->scan_param_setup_cback = scan_param_setup_cback;
-
     bta_sys_sendmsg(p_msg);
 }
 #endif  // BLE_INCLUDED == TRUE
@@ -1456,18 +1546,19 @@
 **
 *******************************************************************************/
 void BTA_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
-                            tBTA_BLE_AD_MASK data_mask,
+                            tBTA_BLE_AD_MASK data_mask, UINT8 frag_pref,
                             tBTA_BLE_ADV_DATA *p_data)
 {
-  tBTA_DM_API_BLE_MULTI_ADV_DATA *p_msg = osi_calloc(sizeof(*p_msg));
+    tBTA_DM_API_BLE_MULTI_ADV_DATA *p_msg = osi_calloc(sizeof(*p_msg));
 
-  p_msg->hdr.event = BTA_DM_API_BLE_MULTI_ADV_DATA_EVT;
-  p_msg->inst_id = inst_id;
-  p_msg->is_scan_rsp = is_scan_rsp;
-  p_msg->data_mask = data_mask;
-  memcpy(&p_msg->data, p_data, sizeof(p_msg->data));
+    p_msg->hdr.event     = BTA_DM_API_BLE_MULTI_ADV_DATA_EVT;
+    p_msg->inst_id      = inst_id;
+    p_msg->is_scan_rsp  = is_scan_rsp;
+    p_msg->data_mask     = data_mask;
+    memcpy(&p_msg->data, p_data, sizeof(p_msg->data));
+    p_msg->frag_pref     = frag_pref;
 
-  bta_sys_sendmsg(p_msg);
+    bta_sys_sendmsg(p_msg);
 }
 
 /*******************************************************************************
@@ -1793,6 +1884,59 @@
     bta_sys_sendmsg(p_msg);
 }
 
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetPhy
+**
+** Description      This function is to set Tx and Rx Phy for a connection
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleSetPhy(BD_ADDR remote_device, UINT8 all_phy, UINT8 tx_phy,
+                     UINT8 rx_phy, UINT16 phy_options)
+{
+    tBTA_DM_API_BLE_SET_PHY *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_SET_PHY *)osi_malloc(sizeof(tBTA_DM_API_BLE_SET_PHY)))
+                  != NULL)
+    {
+        bdcpy(p_msg->remote_bda, remote_device);
+        p_msg->all_phy = all_phy;
+        p_msg->tx_phy = tx_phy;
+        p_msg->rx_phy = rx_phy;
+        p_msg->phy_options = phy_options;
+        p_msg->hdr.event = BTA_DM_API_SET_BLE_PHY_EVT;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetDefaultPhy
+**
+** Description      This function is to set default Tx and Rx Phy
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleSetDefaultPhy(UINT8 all_phy, UINT8 tx_phy, UINT8 rx_phy)
+{
+    tBTA_DM_API_BLE_SET_DEFAULT_PHY *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_SET_DEFAULT_PHY *)osi_malloc(sizeof(tBTA_DM_API_BLE_SET_DEFAULT_PHY)))
+                  != NULL)
+    {
+        p_msg->all_phy = all_phy;
+        p_msg->tx_phy = tx_phy;
+        p_msg->rx_phy = rx_phy;
+        p_msg->hdr.event = BTA_DM_API_SET_DEFAULT_BLE_PHY_EVT;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
 #endif
 
 /*******************************************************************************
@@ -1877,7 +2021,7 @@
 ** Returns          void.
 **
 *******************************************************************************/
-extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
+extern void BTA_DmBleObserve(BOOLEAN start, UINT16 duration, UINT16 period,
                              tBTA_DM_SEARCH_CBACK *p_results_cb)
 {
     tBTA_DM_API_BLE_OBSERVE *p_msg =
@@ -1888,6 +2032,7 @@
     p_msg->hdr.event = BTA_DM_API_BLE_OBSERVE_EVT;
     p_msg->start = start;
     p_msg->duration = duration;
+    p_msg->period = period;
     p_msg->p_cback = p_results_cb;
 
     bta_sys_sendmsg(p_msg);
diff --git a/bta/dm/bta_dm_cfg.c b/bta/dm/bta_dm_cfg.c
index 744a6fc..b5a6d41 100644
--- a/bta/dm/bta_dm_cfg.c
+++ b/bta/dm/bta_dm_cfg.c
@@ -56,6 +56,15 @@
 #define tBTA_DM_PM_TYPE_QUALIFIER
 #endif
 
+/* Reduce Idle timeout value due to intermediate timer */
+#ifndef BTA_JVS_IDLE_TO_SNIFF_DELAY_MS
+#define BTA_JVS_IDLE_TO_SNIFF_DELAY_MS (BTA_FTS_OPS_IDLE_TO_SNIFF_DELAY_MS - BTA_JV_IDLE_TIMEOUT_MS)
+#endif
+
+#ifndef BTA_JVC_IDLE_TO_SNIFF_DELAY_MS
+#define BTA_JVC_IDLE_TO_SNIFF_DELAY_MS (5000 - BTA_JV_IDLE_TIMEOUT_MS)
+#endif
+
 
 const tBTA_DM_CFG bta_dm_cfg =
 {
@@ -170,7 +179,7 @@
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* app close */
       {{BTA_DM_PM_SNIFF_SCO_OPEN_IDX, 7000},   {BTA_DM_PM_NO_ACTION, 0}},   /* sco open, active */
       {{BTA_DM_PM_SNIFF_A2DP_IDX,  7000},   {BTA_DM_PM_NO_ACTION, 0}},   /* sco close sniff  */
-      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* idle */
+      {{BTA_DM_PM_SNIFF, 7000},   {BTA_DM_PM_NO_ACTION, 0}},   /* idle */
       {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},   /* busy */
       {{BTA_DM_PM_RETRY,  7000},   {BTA_DM_PM_NO_ACTION, 0}}    /* mode change retry */
   }
@@ -284,7 +293,7 @@
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
-      {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_SNIFF_A2DP_IDX, BTA_JVC_IDLE_TO_SNIFF_DELAY_MS},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
       {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
   }
@@ -303,7 +312,7 @@
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
-      {{BTA_DM_PM_SNIFF_A2DP_IDX, BTA_FTS_OPS_IDLE_TO_SNIFF_DELAY_MS}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+      {{BTA_DM_PM_SNIFF_A2DP_IDX, BTA_JVS_IDLE_TO_SNIFF_DELAY_MS}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
       {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
   }
@@ -495,6 +504,7 @@
   {BTA_DM_PM_SNIFF3_MAX, BTA_DM_PM_SNIFF3_MIN, BTA_DM_PM_SNIFF3_ATTEMPT, BTA_DM_PM_SNIFF3_TIMEOUT, BTM_PM_MD_SNIFF}, /* for BTA_DM_PM_SNIFF3- SCO open */
   {BTA_DM_PM_SNIFF4_MAX, BTA_DM_PM_SNIFF4_MIN, BTA_DM_PM_SNIFF4_ATTEMPT, BTA_DM_PM_SNIFF4_TIMEOUT, BTM_PM_MD_SNIFF}, /* for BTA_DM_PM_SNIFF4- HD active */
   {BTA_DM_PM_SNIFF5_MAX, BTA_DM_PM_SNIFF5_MIN, BTA_DM_PM_SNIFF5_ATTEMPT, BTA_DM_PM_SNIFF5_TIMEOUT, BTM_PM_MD_SNIFF}, /* for BTA_DM_PM_SNIFF5- HD active */
+  {BTA_DM_PM_SNIFF6_MAX, BTA_DM_PM_SNIFF6_MIN, BTA_DM_PM_SNIFF6_ATTEMPT, BTA_DM_PM_SNIFF6_TIMEOUT, BTM_PM_MD_SNIFF}, /* for BTA_DM_PM_SNIFF6- HH active */
   {BTA_DM_PM_PARK_MAX, BTA_DM_PM_PARK_MIN, BTA_DM_PM_PARK_ATTEMPT, BTA_DM_PM_PARK_TIMEOUT, BTM_PM_MD_PARK}
 
 #ifdef BTE_SIM_APP      /* For Insight builds only */
diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h
index a5fe0ad..3e8a2422 100644
--- a/bta/dm/bta_dm_int.h
+++ b/bta/dm/bta_dm_int.h
@@ -98,6 +98,8 @@
     BTA_DM_API_BLE_SET_SCAN_RSP_EVT,
     BTA_DM_API_BLE_BROADCAST_EVT,
     BTA_DM_API_SET_DATA_LENGTH_EVT,
+    BTA_DM_API_SET_BLE_PHY_EVT,
+    BTA_DM_API_SET_DEFAULT_BLE_PHY_EVT,
 
 #if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
     BTA_DM_API_CFG_FILTER_COND_EVT,
@@ -122,6 +124,8 @@
     BTA_DM_API_EXECUTE_CBACK_EVT,
     BTA_DM_API_REMOVE_ALL_ACL_EVT,
     BTA_DM_API_REMOVE_DEVICE_EVT,
+    BTA_DM_API_HCI_RAW_COMMAND_EVT,
+    BTA_DM_API_VENDOR_SPECIFIC_COMMAND_EVT,
     BTA_DM_MAX_EVT
 };
 
@@ -167,6 +171,26 @@
     UINT8           conn_paired_only;
 } tBTA_DM_API_SET_VISIBILITY;
 
+/* data type for BTA_DM_API_HCI_RAW_COMMAND_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT16              opcode;
+    UINT8               param_len;
+    UINT8               *p_param_buf;
+    tBTA_RAW_CMPL_CBACK *p_cback;
+} tBTA_DM_API_RAW_COMMAND;
+
+/* data type for BTA_DM_API_VENDOR_SPECIFIC_COMMAND_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT16              opcode;
+    UINT8               param_len;
+    UINT8               *p_param_buf;
+    tBTA_VENDOR_CMPL_CBACK *p_cback;
+} tBTA_DM_API_VENDOR_SPECIFIC_COMMAND;
+
 enum
 {
     BTA_DM_RS_NONE,     /* straight API call */
@@ -458,8 +482,11 @@
 {
     BT_HDR hdr;
     tBTA_GATTC_IF client_if;
+    UINT8  scan_phys;
     UINT32 scan_int;
     UINT32 scan_window;
+    UINT16 scan_int_coded;
+    UINT16 scan_window_coded;
     tBLE_SCAN_MODE scan_mode;
     tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback;
 }tBTA_DM_API_BLE_SCAN_PARAMS;
@@ -478,6 +505,7 @@
     BT_HDR                  hdr;
     BOOLEAN                 start;
     UINT16                  duration;
+    UINT16                  period;
     tBTA_DM_SEARCH_CBACK * p_cback;
 }tBTA_DM_API_BLE_OBSERVE;
 
@@ -488,6 +516,24 @@
     UINT16      tx_data_length;
 }tBTA_DM_API_BLE_SET_DATA_LENGTH;
 
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR     remote_bda;
+    UINT8       all_phy;
+    UINT8       tx_phy;
+    UINT8       rx_phy;
+    UINT16      phy_options;
+}tBTA_DM_API_BLE_SET_PHY;
+
+typedef struct
+{
+    BT_HDR      hdr;
+    UINT8       all_phy;
+    UINT8       tx_phy;
+    UINT8       rx_phy;
+}tBTA_DM_API_BLE_SET_DEFAULT_PHY;
+
 /* set adv parameter for BLE advertising */
 typedef struct
 {
@@ -527,6 +573,7 @@
     BOOLEAN                 is_scan_rsp;
     tBTA_BLE_AD_MASK        data_mask;
     tBTA_BLE_ADV_DATA       data;
+    UINT8                   frag_pref;
 }tBTA_DM_API_BLE_MULTI_ADV_DATA;
 
 typedef struct
@@ -724,6 +771,8 @@
 #endif
     tBTA_DM_API_UPDATE_CONN_PARAM       ble_update_conn_params;
     tBTA_DM_API_BLE_SET_DATA_LENGTH     ble_set_data_length;
+    tBTA_DM_API_BLE_SET_PHY             ble_set_phy;
+    tBTA_DM_API_BLE_SET_DEFAULT_PHY     ble_set_default_phy;
 
     tBTA_DM_API_BLE_MULTI_ADV_ENB       ble_multi_adv_enb;
     tBTA_DM_API_BLE_MULTI_ADV_PARAM     ble_multi_adv_param;
@@ -740,11 +789,16 @@
 
     tBTA_DM_API_REMOVE_ACL              remove_acl;
     tBTA_DM_API_REMOVE_ALL_ACL          remove_all_acl;
-
+    tBTA_DM_API_RAW_COMMAND             btc_command;
+    tBTA_DM_API_VENDOR_SPECIFIC_COMMAND vendor_command;
 } tBTA_DM_MSG;
 
-
+#ifndef MAX_ACL_CONNECTIONS
 #define BTA_DM_NUM_PEER_DEVICE 7
+#else
+#define BTA_DM_NUM_PEER_DEVICE  MAX_ACL_CONNECTIONS
+#endif
+
 
 #define BTA_DM_NOT_CONNECTED  0
 #define BTA_DM_CONNECTED      1
@@ -885,6 +939,10 @@
     BD_ADDR                     pin_bd_addr;
     DEV_CLASS                   pin_dev_class;
     tBTA_DM_SEC_EVT             pin_evt;
+    tBTA_IO_CAP                 loc_io_caps;    /* IO Capabilities of local device */
+    tBTA_IO_CAP                 rmt_io_caps;    /* IO Capabilities of remote device */
+    tBTA_AUTH_REQ               loc_auth_req;   /* Authentication required for local device */
+    tBTA_AUTH_REQ               rmt_auth_req;
     UINT32          num_val;        /* the numeric value for comparison. If just_works, do not show this number to UI */
     BOOLEAN         just_works;     /* TRUE, if "Just Works" association model */
 #if ( BTA_EIR_CANNED_UUID_LIST != TRUE )
@@ -1115,6 +1173,8 @@
 extern void bta_dm_ble_set_scan_rsp (tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_set_data_length(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_phy(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_default_phy(tBTA_DM_MSG *p_data);
 
 #if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
 extern void bta_dm_cfg_filter_cond (tBTA_DM_MSG *p_data);
@@ -1175,4 +1235,5 @@
 
 
 extern void bta_dm_remove_all_acl(tBTA_DM_MSG *p_data);
+extern void bta_dm_hci_raw_command(tBTA_DM_MSG *p_data);
 #endif /* BTA_DM_INT_H */
diff --git a/bta/dm/bta_dm_main.c b/bta/dm/bta_dm_main.c
index e6d791a..4e51183 100644
--- a/bta/dm/bta_dm_main.c
+++ b/bta/dm/bta_dm_main.c
@@ -96,6 +96,8 @@
     bta_dm_ble_set_scan_rsp,       /* BTA_DM_API_BLE_SET_SCAN_RSPT */
     bta_dm_ble_broadcast,          /* BTA_DM_API_BLE_BROADCAST_EVT */
     bta_dm_ble_set_data_length,    /* BTA_DM_API_SET_DATA_LENGTH_EVT */
+    bta_dm_ble_set_phy,            /* BTA_DM_API_SET_BLE_PHY_EVT */
+    bta_dm_ble_set_default_phy,    /* BTA_DM_API_SET_BLE_DEFAULT_PHY_EVT */
 #if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
     bta_dm_cfg_filter_cond,         /* BTA_DM_API_CFG_FILTER_COND_EVT */
     bta_dm_scan_filter_param_setup, /* BTA_DM_API_SCAN_FILTER_SETUP_EVT */
@@ -119,6 +121,8 @@
 
     bta_dm_remove_all_acl,      /* BTA_DM_API_REMOVE_ALL_ACL_EVT */
     bta_dm_remove_device,       /* BTA_DM_API_REMOVE_DEVICE_EVT */
+    bta_dm_hci_raw_command,    /* BTA_DM_API_HCI_RAW_COMMAND_EVT */
+    bta_dm_vendor_spec_command,/* BTA_DM_API_VENDOR_SPECIFIC_COMMAND_EVT */
 };
 
 
@@ -358,7 +362,7 @@
     /* execute action functions */
     for (i = 0; i < BTA_DM_SEARCH_ACTIONS; i++)
     {
-        if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_DM_SEARCH_IGNORE)
+        if ((action = state_table[p_msg->event & 0x00ff][i]) < BTA_DM_SEARCH_IGNORE)
         {
             (*bta_dm_search_action[action])( (tBTA_DM_MSG*) p_msg);
         }
diff --git a/bta/dm/bta_dm_pm.c b/bta/dm/bta_dm_pm.c
index bbd4fed..0602022 100644
--- a/bta/dm/bta_dm_pm.c
+++ b/bta/dm/bta_dm_pm.c
@@ -32,6 +32,7 @@
 #include "bta_dm_int.h"
 #include "btm_api.h"
 
+#include "device/include/interop.h"
 
 extern fixed_queue_t *btu_bta_alarm_queue;
 
@@ -46,6 +47,7 @@
 static int bta_dm_get_sco_index();
 static void bta_dm_pm_hid_check(BOOLEAN bScoActive);
 static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisable);
+void bta_dm_pm_set_sniff_policy_toggle(BD_ADDR peer_addr, BOOLEAN bDisable);
 static void bta_dm_pm_stop_timer_by_index(tBTA_PM_TIMER *p_timer,
                                           UINT8 timer_idx);
 
@@ -410,6 +412,9 @@
         {
             bta_dm_conn_srvcs.count--;
 
+            APPL_TRACE_DEBUG("%s: Removed power mode entry for service id = %d, count = %d",
+                               __func__, p_bta_dm_pm_cfg[i].id, bta_dm_conn_srvcs.count);
+
             for(; j<bta_dm_conn_srvcs.count ; j++)
             {
 
@@ -442,6 +447,9 @@
 
         bta_dm_conn_srvcs.count++;
         bta_dm_conn_srvcs.conn_srvc[j].state = status;
+
+        APPL_TRACE_WARNING("%s: new conn_srvc id:%d, app_id:%d count:%d", __func__,
+                             id, app_id, bta_dm_conn_srvcs.count);
     }
     else
     {
@@ -470,7 +478,21 @@
 #endif
        )
     {
-        bta_dm_pm_ssr(peer_addr);
+        if( ((NULL != (p = BTM_ReadLocalFeatures ())) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) &&
+            ((NULL != (p = BTM_ReadRemoteFeatures (peer_addr))) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)))
+        {
+            /* If HID connection open is received and SCO is already active.
+               This will handle the case where HID connects when SCO already active */
+            if ((status == BTA_SYS_CONN_OPEN) && (id == BTA_ID_HH) && bta_dm_pm_is_sco_active())
+            {
+                APPL_TRACE_DEBUG("%s: SCO is Active, disabling SSR on HID link", __func__)
+                BTM_SetSsrParams(peer_addr, 0, 0, 0);
+            }
+            else
+            {
+                bta_dm_pm_ssr(peer_addr);
+            }
+        }
     }
     else
     {
@@ -490,28 +512,53 @@
             }
         }
     }
+
+    /* If HID connection open is received and SCO is already active.
+       disable snii link policy for some devices */
+    if ((status == BTA_SYS_CONN_OPEN) && (id == BTA_ID_HH) && bta_dm_pm_is_sco_active())
+    {
+        /* Check if DUT is slave on SCO Link to decide if sniff needs to be disabled or not */
+        UINT8 role_on_sco_link;
+        BTM_GetRole(bta_dm_conn_srvcs.conn_srvc[bta_dm_get_sco_index()].peer_bdaddr,
+                &role_on_sco_link);
+        APPL_TRACE_DEBUG("%s: Role on SCO Link = %d", __func__, role_on_sco_link);
+        if (role_on_sco_link == BTM_ROLE_SLAVE)
+        {
+            UINT16 manufacturer = 0;
+            UINT16  lmp_sub_version = 0;
+            UINT8 lmp_version = 0;
+            tBTA_DM_PEER_DEVICE *p_rem_dev = NULL;
+            if (BTM_ReadRemoteVersion(peer_addr, &lmp_version,
+                &manufacturer, &lmp_sub_version) == BTM_SUCCESS) {
+                bt_bdaddr_t remote_bdaddr;
+                bdcpy(remote_bdaddr.address, peer_addr);
+                p_rem_dev = bta_dm_find_peer_device(peer_addr);
+                /* Disable sniff policy on the HID link since SCO is Up on Slave Link */
+                if ((p_rem_dev) && (interop_match_addr(
+                    INTEROP_DISABLE_SNIFF_DURING_SCO, (const bt_bdaddr_t *)&remote_bdaddr) ||
+                    interop_match_manufacturer(INTEROP_DISABLE_SNIFF_DURING_SCO, manufacturer)))
+                {
+                    char buf[18];
+                    APPL_TRACE_DEBUG("%s: disable sniff for manufacturer:%d addr = %s",
+                        __func__, manufacturer, bdaddr_to_string((const bt_bdaddr_t *)peer_addr,
+                        buf, sizeof(buf)));
+                    bta_dm_pm_set_sniff_policy(p_rem_dev, true);
+                }
+            }
+        }
+    }
+
+    /* If SCO up/down event is received, then enable/disable SSR on active HID link */
+    if (status == BTA_SYS_SCO_OPEN || status == BTA_SYS_SCO_CLOSE)
+    {
+        const bool bScoActive = (status == BTA_SYS_SCO_OPEN);
+
+        APPL_TRACE_DEBUG("%s: bta_dm_pm_hid_check with bScoActive = %d", __func__, bScoActive);
+        bta_dm_pm_hid_check(bScoActive);
+    }
 #endif
 
     bta_dm_pm_set_mode(peer_addr, BTA_DM_PM_NO_ACTION, pm_req);
-
-    /* perform the HID link workaround if needed
-    ** 1. If SCO up/down event is received OR
-    ** 2. If HID connection open is received and SCO is already active.
-    **     This will handle the case where HID connects when SCO already active
-    */
-    if ( BTM_IsDeviceUp() &&
-         ( ((status == BTA_SYS_SCO_OPEN) || (status == BTA_SYS_SCO_CLOSE)) ||
-           ((status == BTA_SYS_CONN_OPEN) && (id == BTA_ID_HH) && bta_dm_pm_is_sco_active()) ) )
-    {
-        BOOLEAN bScoActive;
-        if (status == BTA_SYS_CONN_OPEN)
-            bScoActive = TRUE;
-        else
-            bScoActive = (status == BTA_SYS_SCO_OPEN);
-
-        bta_dm_pm_hid_check(bScoActive);
-    }
-
 }
 
 
@@ -860,6 +907,24 @@
             {
                 if (bta_hh_read_ssr_param(peer_addr, &p_spec_cur->max_lat, &p_spec_cur->min_rmt_to) == BTA_HH_ERR)
                     continue;
+                if (p_spec_cur->max_lat == BTA_HH_SSR_MAX_LATENCY_ZERO)
+                {
+                    APPL_TRACE_WARNING("%s: Max latency is 0, not sending"
+                        "SSR command as device is blacklisted", __func__);
+                    return;
+                }
+                else if (p_spec_cur->max_lat == BTA_HH_SSR_DISABLE_SSR)
+                {
+                    APPL_TRACE_WARNING("%s: Need to disable SSR"
+                        "as device is blacklisted", __func__);
+                    BTM_SetSsrParams (peer_addr, 0, 0, 0);
+                    return;
+                }
+                else if (p_spec_cur->max_lat < BTA_HH_SSR_MAX_LATENCY_MIN_OPTIMAL)
+                {
+                    p_spec_cur->max_lat = BTA_HH_SSR_MAX_LATENCY_MIN_OPTIMAL;
+                }
+                APPL_TRACE_DEBUG("%s: New Max Latency = %d", __func__, p_spec_cur->max_lat);
             }
 #endif
             if (p_spec_cur->max_lat < p_spec->max_lat ||
@@ -880,7 +945,7 @@
         if (bta_dm_pm_is_sco_active())
         {
             int idx = bta_dm_get_sco_index();
-            if (idx != -1)
+            if (idx != -1 && idx < bta_dm_conn_srvcs.count)
             {
                 if (bdcmp(bta_dm_conn_srvcs.conn_srvc[idx].peer_bdaddr, peer_addr) == 0)
                 {
@@ -1195,34 +1260,87 @@
 **
 ** Function         bta_dm_pm_hid_check
 **
-** Description      Disables/Enables sniff in link policy based on SCO Up/Down
+** Description      Disables/Enables SSR based on SCO Up/Down
 **
 ** Returns          None
 **
 *******************************************************************************/
 static void bta_dm_pm_hid_check(BOOLEAN bScoActive)
 {
-    int j;
+    BD_ADDR peer_bdaddr;
+    UINT8 role_on_sco_link;
 
-    /* if HID is active, disable the link policy */
-    for(j=0; j<bta_dm_conn_srvcs.count ; j++)
+    if (bScoActive)
     {
-        /* check if an entry already present */
-        if(bta_dm_conn_srvcs.conn_srvc[j].id == BTA_ID_HH )
+        /* Check if DUT is slave on SCO Link */
+        BTM_GetRole(bta_dm_conn_srvcs.conn_srvc[bta_dm_get_sco_index()].peer_bdaddr,
+                &role_on_sco_link);
+        APPL_TRACE_DEBUG("%s: Role on SCO Link = %d", __func__, role_on_sco_link);
+    }
+    for (int j = 0; j < bta_dm_conn_srvcs.count ; j ++)
+    {
+        /* check if HID entry already present */
+        if (((bScoActive && (role_on_sco_link == BTM_ROLE_SLAVE)) || !bScoActive) &&
+            bta_dm_conn_srvcs.conn_srvc[j].id == BTA_ID_HH)
         {
-            APPL_TRACE_DEBUG ("SCO status change(Active: %d), modify HID link policy. state: %d",
-                bScoActive, bta_dm_conn_srvcs.conn_srvc[j].state);
-            bta_dm_pm_set_sniff_policy( bta_dm_find_peer_device(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr), bScoActive);
+            UINT16 manufacturer = 0;
+            UINT16  lmp_sub_version = 0;
+            UINT8 lmp_version = 0;
+            tBTA_DM_PEER_DEVICE *p_rem_dev = NULL;
+            UINT8 *p = BTM_ReadLocalFeatures();
+            bt_bdaddr_t remote_address;
+            bdcpy(peer_bdaddr, bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr);
+            bdcpy(remote_address.address, bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr);
 
-            /* if we had disabled link policy, seems like the hid device stop retrying SNIFF after a few tries. force sniff if needed */
-            if (!bScoActive)
-                bta_dm_pm_set_mode(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, BTA_DM_PM_NO_ACTION,
-                                   BTA_DM_PM_RESTART);
+            if (BTM_ReadRemoteVersion(peer_bdaddr, &lmp_version,
+                &manufacturer, &lmp_sub_version) == BTM_SUCCESS) {
+                p_rem_dev = bta_dm_find_peer_device(peer_bdaddr);
+                /* Disable/Enable sniff policy on the HID link if SCO Up/Down*/
+                if ((p_rem_dev) && (interop_match_addr(
+                    INTEROP_DISABLE_SNIFF_DURING_SCO, (const bt_bdaddr_t *)&remote_address) ||
+                    interop_match_manufacturer(INTEROP_DISABLE_SNIFF_DURING_SCO, manufacturer)))
+                {
+                    char buf[18];
+                    APPL_TRACE_DEBUG("%s: %s sniff for manufacturer:%d",
+                        __func__, bScoActive ? "disable" : "enable", manufacturer,
+                        bdaddr_to_string((const bt_bdaddr_t *)peer_bdaddr, buf, sizeof(buf)));
+                    bta_dm_pm_set_sniff_policy(p_rem_dev, bScoActive);
+                    /* Put link in sniff with specific parameters since SCO is disconnected */
+                    if (!bScoActive)
+                        /*
+                         * Put HID link in sniff also with specific HID Sniff parameters as remote
+                         * device might not attempt sniff in case SCO is connected for longer time.
+                         */
+                        bta_dm_pm_sniff(p_rem_dev, (BTA_DM_PM_SNIFF6 & 0x0F));
+                }
+            }
+
+            if((p != NULL && HCI_SNIFF_SUB_RATE_SUPPORTED(p))
+                &&((NULL != (p = BTM_ReadRemoteFeatures (peer_bdaddr)))
+                && HCI_SNIFF_SUB_RATE_SUPPORTED(p)))
+            {
+                if (bScoActive)
+                {
+                    APPL_TRACE_DEBUG("%s: SCO_OPEN, disabling SSR", __func__);
+                    BTM_SetSsrParams(peer_bdaddr, 0, 0, 0);
+                }
+                else
+                {
+                    APPL_TRACE_DEBUG("%s: SCO_CLOSE, enabling SSR", __func__);
+                    bta_dm_pm_ssr(peer_bdaddr);
+                }
+            }
         }
     }
 
 }
-
+void bta_dm_pm_set_sniff_policy_toggle(BD_ADDR peer_addr, BOOLEAN bDisable)
+{
+    APPL_TRACE_DEBUG("%s: bDisable:%d", __func__, bDisable);
+    tBTA_DM_PEER_DEVICE *p_dev = NULL;
+    p_dev = bta_dm_find_peer_device(peer_addr);
+    bta_dm_pm_set_sniff_policy(p_dev, bDisable);
+}
 /*******************************************************************************
 **
 ** Function         bta_dm_pm_set_sniff_policy
diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
index 3390b94..302f2bd 100644
--- a/bta/gatt/bta_gattc_act.c
+++ b/bta/gatt/bta_gattc_act.c
@@ -36,6 +36,7 @@
 #include "osi/include/log.h"
 #include "stack/l2cap/l2c_int.h"
 #include "utl.h"
+#include "btm_int.h"
 
 #if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
 #include "bta_hh_int.h"
@@ -803,6 +804,9 @@
     if (p_clcb->transport == BTA_TRANSPORT_BR_EDR)
         bta_sys_conn_close( BTA_ID_GATTC ,BTA_ALL_APP_ID, p_clcb->bda);
 
+    if (!btm_sec_is_a_bonded_dev(p_clcb->bda))
+        BTA_GATTC_Refresh(p_clcb->bda);
+
     bta_gattc_clcb_dealloc(p_clcb);
 
     if (p_data->hdr.event == BTA_GATTC_API_CLOSE_EVT)
@@ -822,6 +826,7 @@
     {
         bta_gattc_deregister_cmpl(p_clreg);
     }
+    bta_gattc_clear_notif_reg_on_disc(p_clreg, p_clcb->bda);
 }
 /*******************************************************************************
 **
@@ -1820,6 +1825,12 @@
     /* if non-service change indication/notification, forward to application */
     if (!bta_gattc_process_srvc_chg_ind(conn_id, p_clrcb, p_srcb, p_clcb, &notify, &p_data->att_value))
     {
+        /* Not a service change indication, check for an unallocated HID conn */
+        if (bta_hh_le_is_hh_gatt_if(gatt_if) && !p_clcb)
+        {
+            APPL_TRACE_ERROR("%s, ignore HID ind/notificiation", __func__);
+            return;
+        }
         /* if app registered for the notification */
         if (bta_gattc_check_notif_registry(p_clrcb, p_srcb, &notify))
         {
diff --git a/bta/gatt/bta_gattc_cache.c b/bta/gatt/bta_gattc_cache.c
index 45d2588..8ac3a88 100644
--- a/bta/gatt/bta_gattc_cache.c
+++ b/bta/gatt/bta_gattc_cache.c
@@ -82,11 +82,23 @@
 };
 /* utility functions */
 
-bool display_cache_attribute(void *data, void *context) {
-    tBTA_GATTC_CACHE_ATTR *p_attr = data;
-    APPL_TRACE_ERROR("\t Attr handle[%d] uuid[0x%04x] type[%s] prop[0x%1x]",
-                      p_attr->handle, p_attr->uuid.uu.uuid16,
-                      bta_gattc_attr_type[p_attr->attr_type], p_attr->property);
+bool display_cache_descriptor(void *data, void *context) {
+    tBTA_GATTC_DESCRIPTOR *p_desc = data;
+    APPL_TRACE_ERROR("Descriptor handle[%d] uuid[0x%04x]",
+                      p_desc->handle, p_desc->uuid.uu.uuid16);
+
+    return true;
+}
+
+bool display_cache_characteristic(void *data, void *context) {
+    tBTA_GATTC_CHARACTERISTIC *p_char = data;
+    APPL_TRACE_ERROR("Characteristic handle[%d] uuid[0x%04x] prop[0x%1x]",
+                      p_char->handle, p_char->uuid.uu.uuid16, p_char->properties);
+
+    if (p_char->descriptors != NULL) {
+        list_foreach(p_char->descriptors, display_cache_descriptor, NULL);
+    }
+
     return true;
 }
 
@@ -99,7 +111,7 @@
                       p_cur_srvc->handle);
 
     if (p_cur_srvc->characteristics != NULL) {
-        list_foreach(p_cur_srvc->characteristics, display_cache_attribute, NULL);
+        list_foreach(p_cur_srvc->characteristics, display_cache_characteristic, NULL);
     }
 
     return true;
@@ -509,7 +521,8 @@
     LOG_WARN(LOG_TAG, "%s no more services found", __func__);
 
 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-    bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
+    if(p_srvc_cb->p_srvc_cache)
+        bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
 #endif
     /* save cache to NV */
     p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
@@ -582,7 +595,7 @@
 {
     tBTA_GATTC_ATTR_REC *p_rec = NULL;
 
-    if (-- p_srvc_cb->total_char > 0)
+    if((p_srvc_cb->total_char != 0) && (-- p_srvc_cb->total_char > 0))
     {
         p_rec = p_srvc_cb->p_srvc_list + (++ p_srvc_cb->cur_char_idx);
         /* add the next characteristic into cache */
@@ -592,8 +605,8 @@
                                      &p_rec->uuid,
                                      p_rec->property);
 
-        /* start discoverying next characteristic for char descriptor */
-        bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
+           /* start discoverying next characteristic for char descriptor */
+           bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
     }
     else
     /* all characteristic has been explored, start with next service if any */
@@ -1328,6 +1341,7 @@
     if (!p_clcb->p_srcb || p_clcb->p_srcb->p_srvc_list || /* no active discovery */
         !p_clcb->p_srcb->p_srvc_cache) {
         APPL_TRACE_ERROR("No server cache available");
+        return;
     }
 
     bta_gattc_get_gatt_db_impl(p_clcb->p_srcb, start_handle, end_handle, db, count);
@@ -1630,6 +1644,10 @@
     BTIF_TRACE_DEBUG("%s", __func__);
     char fname[255] = {0};
     bta_gattc_generate_cache_file_name(fname, server_bda);
+
+    if(!remove(fname))
+        BTIF_TRACE_DEBUG("%s GATT cache deleted successfully", __func__);
+
     unlink(fname);
 }
 #endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gattc_int.h b/bta/gatt/bta_gattc_int.h
index d895864..88c39a9 100644
--- a/bta/gatt/bta_gattc_int.h
+++ b/bta/gatt/bta_gattc_int.h
@@ -79,7 +79,11 @@
 
 /* max known devices GATTC can support */
 #ifndef     BTA_GATTC_KNOWN_SR_MAX
+#ifndef MAX_ACL_CONNECTIONS
 #define     BTA_GATTC_KNOWN_SR_MAX    10
+#else
+#define     BTA_GATTC_KNOWN_SR_MAX    MAX_ACL_CONNECTIONS
+#endif
 #endif
 
 #define BTA_GATTC_CONN_MAX      GATT_MAX_PHY_CHANNEL
@@ -296,7 +300,11 @@
 } tBTA_GATTC_SERV;
 
 #ifndef BTA_GATTC_NOTIF_REG_MAX
+#ifndef MAX_ACL_CONNECTIONS
 #define BTA_GATTC_NOTIF_REG_MAX     15
+#else
+#define BTA_GATTC_NOTIF_REG_MAX     MAX_ACL_CONNECTIONS*3
+#endif
 #endif
 
 typedef struct
@@ -471,6 +479,7 @@
 extern BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda, UINT8 role);
 extern UINT8 bta_gattc_num_reg_app(void);
 extern void bta_gattc_clear_notif_registration(tBTA_GATTC_SERV *p_srcb, UINT16 conn_id, UINT16 start_handle, UINT16 end_handle);
+extern void bta_gattc_clear_notif_reg_on_disc(tBTA_GATTC_RCB *p_clreg, BD_ADDR bda);
 extern tBTA_GATTC_SERV * bta_gattc_find_srvr_cache(BD_ADDR bda);
 
 /* discovery functions */
diff --git a/bta/gatt/bta_gattc_utils.c b/bta/gatt/bta_gattc_utils.c
index 8910bd3..f87ea49 100644
--- a/bta/gatt/bta_gattc_utils.c
+++ b/bta/gatt/bta_gattc_utils.c
@@ -476,6 +476,31 @@
     return FALSE;
 
 }
+
+/*******************************************************************************
+**
+** Function         bta_gattc_clear_notif_reg_on_disc
+**
+** Description      clear up the notification registration at disconnection.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_clear_notif_reg_on_disc(tBTA_GATTC_RCB *p_clreg, BD_ADDR bda) {
+    if (!p_clreg) {
+        APPL_TRACE_ERROR("%s, Invalid regiseration block", __func__);
+        return;
+    }
+
+    UINT8 i;
+    for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i++) {
+        if (p_clreg->notif_reg[i].in_use &&
+                !bdcmp(p_clreg->notif_reg[i].remote_bda, bda)) {
+            memset(&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
+        }
+    }
+}
+
 /*******************************************************************************
 **
 ** Function         bta_gattc_clear_notif_registration
diff --git a/bta/hf_client/bta_hf_client_act.c b/bta/hf_client/bta_hf_client_act.c
index d41f298..1126bc7 100644
--- a/bta/hf_client/bta_hf_client_act.c
+++ b/bta/hf_client/bta_hf_client_act.c
@@ -42,6 +42,8 @@
 /* maximum length of data to read from RFCOMM */
 #define BTA_HF_CLIENT_RFC_READ_MAX     512
 
+BOOLEAN is_sniff_disabled = false;
+
 /*******************************************************************************
 **
 ** Function         bta_hf_client_register
@@ -107,6 +109,9 @@
 
     /* disable */
     bta_hf_client_scb_disable();
+
+    if (is_sniff_disabled == true)
+        is_sniff_disabled = false;
 }
 
 /*******************************************************************************
@@ -427,6 +432,9 @@
         bta_hf_client_close_server();
         bta_hf_client_scb_disable();
     }
+
+    if (is_sniff_disabled == true)
+        is_sniff_disabled = false;
 }
 
 /*******************************************************************************
@@ -457,7 +465,7 @@
     }
 
     /* free discovery db */
-    bta_hf_client_free_db(p_data);
+    bta_hf_client_free_db_int(p_data);
 
     /* send ourselves sdp ok/fail event */
     bta_hf_client_sm_execute(event, p_data);
@@ -475,6 +483,7 @@
 *******************************************************************************/
 void bta_hf_client_disc_acp_res(tBTA_HF_CLIENT_DATA *p_data)
 {
+    APPL_TRACE_DEBUG ("%s: Status: %d", __func__, p_data->disc_result.status);
     /* if found service */
     if (p_data->disc_result.status == SDP_SUCCESS ||
         p_data->disc_result.status == SDP_DB_FULL)
@@ -484,7 +493,7 @@
     }
 
     /* free discovery db */
-    bta_hf_client_free_db(p_data);
+    bta_hf_client_free_db_acp(p_data);
 }
 
 /*******************************************************************************
@@ -761,3 +770,56 @@
 
     (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_BINP_EVT, &evt);
 }
+
+/*******************************************************************************
+**
+** Function         bta_hf_client_cgmi
+**
+** Description      Send CGMI event to application.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hf_client_cgmi(char *str)
+{
+    tBTA_HF_CLIENT evt;
+
+    memset(&evt, 0, sizeof(evt));
+
+    strlcpy(evt.cgmi.name, str, BTA_HF_CLIENT_MANUFACTURER_ID + 1);
+
+    (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CGMI_EVT, &evt);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hf_client_cgmm
+**
+** Description      Send CGMM event to application.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hf_client_cgmm(char *str)
+{
+    tBTA_HF_CLIENT evt;
+
+    memset(&evt, 0, sizeof(evt));
+
+    strlcpy(evt.cgmm.model, str, BTA_HF_CLIENT_MANUFACTURER_MODEL + 1);
+
+    APPL_TRACE_DEBUG("%s: phone model is %s", __func__, evt.cgmm.model);
+
+#ifdef SNIFF_DISABLE
+   if (strncmp(evt.cgmm.model, "+CGMM: iPhone", 13) == 0)
+   {
+       APPL_TRACE_WARNING("%s: Changing policy to disable sniff", __func__);
+       bta_sys_clear_policy(BTA_ID_HS, HCI_ENABLE_SNIFF_MODE, bta_hf_client_cb.scb.peer_addr);
+       is_sniff_disabled = true;
+   }
+#endif
+
+    (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CGMM_EVT, &evt);
+}
diff --git a/bta/hf_client/bta_hf_client_at.c b/bta/hf_client/bta_hf_client_at.c
index b273f2f..745d147 100644
--- a/bta/hf_client/bta_hf_client_at.c
+++ b/bta/hf_client/bta_hf_client_at.c
@@ -148,6 +148,7 @@
     bta_hf_client_handle_ok();
   } else {
     APPL_TRACE_ERROR("HFPClient: AT response timeout, disconnecting");
+    GENERATE_VND_LOGS();
     bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL);
   }
 }
@@ -260,17 +261,25 @@
     {
         case BTA_HF_CLIENT_AT_BIA:
         case BTA_HF_CLIENT_AT_BCC:
+        case BTA_HF_CLIENT_AT_CGMI:
+        case BTA_HF_CLIENT_AT_CGMM:
             break;
         case BTA_HF_CLIENT_AT_BCS:
             bta_hf_client_start_at_hold_timer();
             bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE;
             return;
-        case BTA_HF_CLIENT_AT_CLIP: //last cmd is post slc seq
+        case BTA_HF_CLIENT_AT_CLIP:
             if (bta_hf_client_cb.scb.send_at_reply == FALSE)
             {
                 bta_hf_client_cb.scb.send_at_reply = TRUE;
             }
             break;
+        case BTA_HF_CLIENT_AT_CGMI_QUERY:
+            bta_hf_client_send_at_cgmi(FALSE);
+            break;
+        case BTA_HF_CLIENT_AT_CGMM_QUERY:  //last cmd in post slc seq
+            bta_hf_client_send_at_cgmm(FALSE);
+            break;
         case BTA_HF_CLIENT_AT_NONE:
             bta_hf_client_stop_at_hold_timer();
             break;
@@ -302,12 +311,13 @@
     switch(bta_hf_client_cb.scb.at_cb.current_cmd)
     {
         case BTA_HF_CLIENT_AT_BIA:
+        case BTA_HF_CLIENT_AT_CGMI_QUERY:
             break;
         case BTA_HF_CLIENT_AT_BCC:
         case BTA_HF_CLIENT_AT_BCS:
             bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT);
             break;
-        case BTA_HF_CLIENT_AT_CLIP: //last cmd is post slc seq
+        case BTA_HF_CLIENT_AT_CGMM_QUERY: //last cmd in post slc seq
             if (bta_hf_client_cb.scb.send_at_reply == FALSE)
             {
                 bta_hf_client_cb.scb.send_at_reply = TRUE;
@@ -575,6 +585,20 @@
     bta_hf_client_evt_val(BTA_HF_CLIENT_BTRH_EVT, code);
 }
 
+static void bta_hf_client_handle_cgmi(char *manf_id)
+{
+    APPL_TRACE_DEBUG("%s %s", __FUNCTION__, manf_id);
+
+    bta_hf_client_cgmi(manf_id);
+}
+
+static void bta_hf_client_handle_cgmm(char *manf_model)
+{
+    APPL_TRACE_DEBUG("%s %s", __FUNCTION__, manf_model);
+
+    bta_hf_client_cgmm(manf_model);
+}
+
 /******************************************************************************
 **
 **          COMMON AT EVENTS PARSING FUNCTIONS
@@ -1045,8 +1069,8 @@
 {
     UINT16 idx, dir, status, mode, mpty;
     char numstr[33];     /* spec forces 32 chars, plus one for \0*/
-    UINT16 type;
     int res;
+    UINT16 type = 0;
     int offset = 0;
 
     AT_CHECK_EVENT(buffer, "+CLCC:");
@@ -1289,6 +1313,65 @@
     return buffer;
 }
 
+static char *bta_hf_client_parse_cgmi(char *buffer)
+{
+    /* 2048 chars max, plus \0 here */
+    char manf_id[2049];
+    int i = 0;
+
+    // if current cmd is not CGMI, return from here
+    if(bta_hf_client_cb.scb.at_cb.current_cmd != BTA_HF_CLIENT_AT_CGMI)
+        return buffer;
+
+    // no prefix in the response from AG
+    AT_CHECK_EVENT(buffer, "");
+
+    for(; *buffer != '\r'; i++, buffer++)
+        manf_id[i] = *buffer;
+
+    manf_id[i] = '\0';
+
+    AT_CHECK_RN(buffer);
+
+    bta_hf_client_handle_cgmi(manf_id);
+    // check for OK Response in end
+    AT_CHECK_EVENT(buffer, "OK");
+    AT_CHECK_RN(buffer);
+
+    bta_hf_client_handle_ok();
+
+    return buffer;
+}
+
+static char *bta_hf_client_parse_cgmm(char *buffer)
+{
+    /* 2048 chars max, plus \0 here */
+    char manf_model[2049];
+    int i = 0;
+
+    // if current cmd is not CGMM, return from here
+    if(bta_hf_client_cb.scb.at_cb.current_cmd != BTA_HF_CLIENT_AT_CGMM)
+        return buffer;
+
+    // no prefix in the response from AG
+    AT_CHECK_EVENT(buffer, "");
+
+    for(; *buffer != '\r'; i++, buffer++)
+        manf_model[i] = *buffer;
+
+    manf_model[i] = '\0';
+
+    AT_CHECK_RN(buffer);
+
+    bta_hf_client_handle_cgmm(manf_model);
+    // check for OK Response in end
+    AT_CHECK_EVENT(buffer, "OK");
+    AT_CHECK_RN(buffer);
+
+    bta_hf_client_handle_ok();
+
+    return buffer;
+}
 
 /******************************************************************************
 **       SUPPORTED EVENT MESSAGES
@@ -1325,6 +1408,8 @@
     bta_hf_client_parse_clcc,
     bta_hf_client_parse_cnum,
     bta_hf_client_parse_btrh,
+    bta_hf_client_parse_cgmi,
+    bta_hf_client_parse_cgmm,
     bta_hf_client_parse_busy,
     bta_hf_client_parse_delayed,
     bta_hf_client_parse_no_carrier,
@@ -1924,6 +2009,60 @@
     bta_hf_client_send_at(BTA_HF_CLIENT_AT_BIA, buf, at_len);
 }
 
+void bta_hf_client_send_at_cgmi(BOOLEAN query)
+{
+    char buf[BTA_HF_CLIENT_AT_MAX_LEN];
+    int at_len;
+    tBTA_HF_CLIENT_AT_CMD cmd;
+
+    APPL_TRACE_DEBUG("%s", __FUNCTION__);
+
+    if (query == TRUE)
+    {
+        at_len = snprintf(buf, sizeof(buf), "AT+CGMI=?\r");
+        cmd = BTA_HF_CLIENT_AT_CGMI_QUERY;
+    }
+    else
+    {
+        at_len = snprintf(buf, sizeof(buf), "AT+CGMI\r");
+        cmd = BTA_HF_CLIENT_AT_CGMI;
+    }
+
+    if (at_len < 0)
+    {
+        APPL_TRACE_ERROR("HFPClient: AT command Framing error");
+        return;
+    }
+    bta_hf_client_send_at(cmd, buf, at_len);
+}
+
+void bta_hf_client_send_at_cgmm(BOOLEAN query)
+{
+    char buf[BTA_HF_CLIENT_AT_MAX_LEN];
+    int at_len;
+    tBTA_HF_CLIENT_AT_CMD cmd;
+
+    APPL_TRACE_DEBUG("%s", __FUNCTION__);
+
+    if (query == TRUE)
+    {
+        at_len = snprintf(buf, sizeof(buf), "AT+CGMM=?\r");
+        cmd = BTA_HF_CLIENT_AT_CGMM_QUERY;
+    }
+    else
+    {
+        at_len = snprintf(buf, sizeof(buf), "AT+CGMM\r");
+        cmd = BTA_HF_CLIENT_AT_CGMM;
+    }
+
+    if (at_len < 0)
+    {
+        APPL_TRACE_ERROR("HFPClient: AT command Framing error");
+        return;
+    }
+    bta_hf_client_send_at(cmd, buf, at_len);
+}
+
 void bta_hf_client_at_init(void)
 {
     alarm_free(bta_hf_client_cb.scb.at_cb.resp_timer);
diff --git a/bta/hf_client/bta_hf_client_at.h b/bta/hf_client/bta_hf_client_at.h
index 78b5d63..71ba703 100644
--- a/bta/hf_client/bta_hf_client_at.h
+++ b/bta/hf_client/bta_hf_client_at.h
@@ -70,6 +70,10 @@
     BTA_HF_CLIENT_AT_CNUM,
     BTA_HF_CLIENT_AT_NREC,
     BTA_HF_CLIENT_AT_BINP,
+    BTA_HF_CLIENT_AT_CGMI_QUERY,
+    BTA_HF_CLIENT_AT_CGMI,
+    BTA_HF_CLIENT_AT_CGMM_QUERY,
+    BTA_HF_CLIENT_AT_CGMM,
 };
 
 typedef UINT8 tBTA_HF_CLIENT_AT_CMD;
diff --git a/bta/hf_client/bta_hf_client_int.h b/bta/hf_client/bta_hf_client_int.h
index a2dbde2..521dc94 100644
--- a/bta/hf_client/bta_hf_client_int.h
+++ b/bta/hf_client/bta_hf_client_int.h
@@ -140,7 +140,8 @@
 {
     UINT16              serv_handle;    /* RFCOMM server handle */
     BD_ADDR             peer_addr;      /* peer bd address */
-    tSDP_DISCOVERY_DB   *p_disc_db;     /* pointer to discovery database */
+    tSDP_DISCOVERY_DB   *p_disc_db_int; /* pointer to discovery database for initiator */
+    tSDP_DISCOVERY_DB   *p_disc_db_acp; /* pointer to discovery database for acceptor*/
     UINT16              conn_handle;    /* RFCOMM handle of connected service */
     tBTA_SEC            serv_sec_mask;  /* server security mask */
     tBTA_SEC            cli_sec_mask;   /* client security mask */
@@ -216,7 +217,8 @@
 extern void bta_hf_client_del_record(tBTA_HF_CLIENT_DATA *p_data);
 extern BOOLEAN bta_hf_client_sdp_find_attr(void);
 extern void bta_hf_client_do_disc(void);
-extern void bta_hf_client_free_db(tBTA_HF_CLIENT_DATA *p_data);
+extern void bta_hf_client_free_db_int(tBTA_HF_CLIENT_DATA *p_data);
+extern void bta_hf_client_free_db_acp(tBTA_HF_CLIENT_DATA *p_data);
 
 /* RFCOMM functions */
 extern void bta_hf_client_setup_port(UINT16 handle);
@@ -261,6 +263,8 @@
 extern void bta_hf_client_send_at_nrec(void);
 extern void bta_hf_client_send_at_binp(UINT32 action);
 extern void bta_hf_client_send_at_bia(void);
+extern void bta_hf_client_send_at_cgmi(BOOLEAN query);
+extern void bta_hf_client_send_at_cgmm(BOOLEAN query);
 
 /* Action functions */
 extern void bta_hf_client_register(tBTA_HF_CLIENT_DATA *p_data);
@@ -287,6 +291,8 @@
 extern void bta_hf_client_clcc(UINT32 idx, BOOLEAN incoming, UINT8 status, BOOLEAN mpty, char *number);
 extern void bta_hf_client_cnum(char *number, UINT16 service);
 extern void bta_hf_client_binp(char *number);
+extern void bta_hf_client_cgmi(char *str);
+extern void bta_hf_client_cgmm(char *str);
 
 /* Commands handling functions */
 extern void bta_hf_client_dial(tBTA_HF_CLIENT_DATA *p_data);
diff --git a/bta/hf_client/bta_hf_client_main.c b/bta/hf_client/bta_hf_client_main.c
index 5df418b..871ac91 100644
--- a/bta/hf_client/bta_hf_client_main.c
+++ b/bta/hf_client/bta_hf_client_main.c
@@ -67,7 +67,8 @@
     BTA_HF_CLIENT_SCO_OPEN,
     BTA_HF_CLIENT_SCO_CLOSE,
     BTA_HF_CLIENT_SCO_SHUTDOWN,
-    BTA_HF_CLIENT_FREE_DB,
+    BTA_HF_CLIENT_FREE_DB_INT,
+    BTA_HF_CLIENT_FREE_DB_ACP,
     BTA_HF_CLIENT_OPEN_FAIL,
     BTA_HF_CLIENT_RFC_OPEN,
     BTA_HF_CLIENT_RFC_FAIL,
@@ -103,7 +104,8 @@
 /* BTA_HF_CLIENT_SCO_OPEN */      bta_hf_client_sco_open,
 /* BTA_HF_CLIENT_SCO_CLOSE */     bta_hf_client_sco_close,
 /* BTA_HF_CLIENT_SCO_SHUTDOWN */  bta_hf_client_sco_shutdown,
-/* BTA_HF_CLIENT_FREE_DB */       bta_hf_client_free_db,
+/* BTA_HF_CLIENT_FREE_DB_INT */   bta_hf_client_free_db_int,
+/* BTA_HF_CLIENT_FREE_DB_ACP */   bta_hf_client_free_db_acp,
 /* BTA_HF_CLIENT_OPEN_FAIL */     bta_hf_client_open_fail,
 /* BTA_HF_CLIENT_RFC_OPEN */      bta_hf_client_rfc_open,
 /* BTA_HF_CLIENT_RFC_FAIL */      bta_hf_client_rfc_fail,
@@ -136,7 +138,7 @@
 /* RFC_CLOSE_EVT */         {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_INIT_ST},
 /* RFC_SRV_CLOSE_EVT */     {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_INIT_ST},
 /* RFC_DATA_EVT */          {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_INIT_ST},
-/* DISC_ACP_RES_EVT */      {BTA_HF_CLIENT_FREE_DB,        BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_INIT_ST},
+/* DISC_ACP_RES_EVT */      {BTA_HF_CLIENT_FREE_DB_ACP,    BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_INIT_ST},
 /* DISC_INT_RES_EVT */      {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_INIT_ST},
 /* DISC_OK_EVT */           {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_INIT_ST},
 /* DISC_FAIL_EVT */         {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_INIT_ST},
@@ -205,8 +207,8 @@
 /* RFC_CLOSE_EVT */         {BTA_HF_CLIENT_RFC_CLOSE,      BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_INIT_ST},
 /* RFC_SRV_CLOSE_EVT */     {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_CLOSING_ST},
 /* RFC_DATA_EVT */          {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_CLOSING_ST},
-/* DISC_ACP_RES_EVT */      {BTA_HF_CLIENT_FREE_DB,        BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_CLOSING_ST},
-/* DISC_INT_RES_EVT */      {BTA_HF_CLIENT_FREE_DB,        BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_INIT_ST},
+/* DISC_ACP_RES_EVT */      {BTA_HF_CLIENT_FREE_DB_ACP,    BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_CLOSING_ST},
+/* DISC_INT_RES_EVT */      {BTA_HF_CLIENT_FREE_DB_INT,    BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_INIT_ST},
 /* DISC_OK_EVT */           {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_CLOSING_ST},
 /* DISC_FAIL_EVT */         {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_CLOSING_ST},
 /* SCO_OPEN_EVT */          {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_CLOSING_ST},
@@ -346,11 +348,22 @@
 
         bta_hf_client_cb.scb.state = BTA_HF_CLIENT_INIT_ST;
 
-        /* Cancel SDP if it had been started. */
-        if(bta_hf_client_cb.scb.p_disc_db)
+        APPL_TRACE_WARNING ("%s:bta_hf_client_cb.scb.role = %d", __func__,
+                                 bta_hf_client_cb.scb.role);
+        /* Cancel SDP if it had been started for initiator. */
+        if (bta_hf_client_cb.scb.p_disc_db_int)
         {
-            (void)SDP_CancelServiceSearch (bta_hf_client_cb.scb.p_disc_db);
-            bta_hf_client_free_db(NULL);
+            APPL_TRACE_WARNING ("%s:cancel SDP serach for the HFP client initiator:", __func__);
+            (void)SDP_CancelServiceSearch (bta_hf_client_cb.scb.p_disc_db_int);
+            bta_hf_client_free_db_int(NULL);
+        }
+
+        /* Cancel SDP if it had been started for acceptor. */
+        if (bta_hf_client_cb.scb.p_disc_db_acp)
+        {
+            APPL_TRACE_WARNING ("%s:cancel SDP serach for the HFP client acceptor:", __func__);
+            (void)SDP_CancelServiceSearch (bta_hf_client_cb.scb.p_disc_db_acp);
+            bta_hf_client_free_db_acp(NULL);
         }
 
         /* reopen registered server */
@@ -388,7 +401,7 @@
 
     /* check if mSBC support enabled */
     osi_property_get("ro.bluetooth.hfp.ver", value, "0");
-    if (strcmp(value,"1.6") == 0)
+    if (strtof(value, NULL) >= 1.6)
     {
        bta_hf_client_cb.msbc_enabled = TRUE;
     }
@@ -511,7 +524,7 @@
     /* execute action functions */
     for (i = 0; i < BTA_HF_CLIENT_ACTIONS; i++)
     {
-        if ((action = state_table[event][i]) != BTA_HF_CLIENT_IGNORE)
+        if ((action = state_table[event][i]) < BTA_HF_CLIENT_IGNORE)
         {
             (*bta_hf_client_action[action])(p_data);
         }
@@ -542,6 +555,8 @@
     bta_hf_client_send_at_cops(FALSE);
     bta_hf_client_send_at_btrh(TRUE, 0);
     bta_hf_client_send_at_clip(TRUE);
+    bta_hf_client_send_at_cgmi(TRUE);
+    bta_hf_client_send_at_cgmm(TRUE);
 }
 
 /*******************************************************************************
diff --git a/bta/hf_client/bta_hf_client_rfc.c b/bta/hf_client/bta_hf_client_rfc.c
index dc422ae..532b852 100644
--- a/bta/hf_client/bta_hf_client_rfc.c
+++ b/bta/hf_client/bta_hf_client_rfc.c
@@ -248,11 +248,21 @@
         p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
         bta_sys_sendmsg(p_buf);
 
-        /* Cancel SDP if it had been started. */
-        if(bta_hf_client_cb.scb.p_disc_db)
+        APPL_TRACE_DEBUG("%s: bta_hf_client_cb.scb.role = %d",__func__, bta_hf_client_cb.scb.role);
+        /* Cancel SDP if it had been started for initiator. */
+        if (bta_hf_client_cb.scb.p_disc_db_int)
         {
-            (void)SDP_CancelServiceSearch (bta_hf_client_cb.scb.p_disc_db);
-            bta_hf_client_free_db(NULL);
+            APPL_TRACE_DEBUG("%s: Cancel SDP service search for the HF client initiator", __func__);
+            (void)SDP_CancelServiceSearch (bta_hf_client_cb.scb.p_disc_db_int);
+            bta_hf_client_free_db_int(NULL);
+        }
+
+        /* Cancel SDP if it had been started for acceptor. */
+        if (bta_hf_client_cb.scb.p_disc_db_acp)
+        {
+            APPL_TRACE_DEBUG("%s: Cancel SDP service search for the HF client acceptor", __func__);
+            (void)SDP_CancelServiceSearch (bta_hf_client_cb.scb.p_disc_db_acp);
+            bta_hf_client_free_db_acp(NULL);
         }
     }
 }
diff --git a/bta/hf_client/bta_hf_client_sdp.c b/bta/hf_client/bta_hf_client_sdp.c
index 822fe97..952cf7d 100644
--- a/bta/hf_client/bta_hf_client_sdp.c
+++ b/bta/hf_client/bta_hf_client_sdp.c
@@ -222,19 +222,22 @@
     BOOLEAN             result = FALSE;
 
     bta_hf_client_cb.scb.peer_version = HFP_VERSION_1_1;   /* Default version */
-
+    APPL_TRACE_DEBUG("%s: bta_hf_client_cb.scb.role = %d",__func__, bta_hf_client_cb.scb.role);
     /* loop through all records we found */
     while (TRUE)
     {
         /* get next record; if none found, we're done */
-        if ((p_rec = SDP_FindServiceInDb(bta_hf_client_cb.scb.p_disc_db, UUID_SERVCLASS_AG_HANDSFREE, p_rec)) == NULL)
-        {
-            break;
-        }
-
-        /* get scn from proto desc list if initiator */
         if (bta_hf_client_cb.scb.role == BTA_HF_CLIENT_INT)
         {
+            APPL_TRACE_DEBUG("%s: find SDP services for HFP client initiator", __func__);
+            if ((p_rec = SDP_FindServiceInDb(bta_hf_client_cb.scb.p_disc_db_int,
+                                             UUID_SERVCLASS_AG_HANDSFREE, p_rec)) == NULL)
+            {
+                APPL_TRACE_DEBUG("%s:initiator p_rec is null", __func__);
+                break;
+            }
+
+            /* get scn from proto desc list if initiator */
             if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe))
             {
                 bta_hf_client_cb.scb.peer_scn = (UINT8) pe.params[0];
@@ -244,6 +247,17 @@
                 continue;
             }
         }
+        /* get next record; if none found, we're done */
+        if (bta_hf_client_cb.scb.role == BTA_HF_CLIENT_ACP)
+        {
+            APPL_TRACE_DEBUG("%s: find SDP services for HFP client acceptor", __func__);
+            if ((p_rec = SDP_FindServiceInDb(bta_hf_client_cb.scb.p_disc_db_acp,
+                                             UUID_SERVCLASS_AG_HANDSFREE, p_rec)) == NULL)
+            {
+                 APPL_TRACE_DEBUG("%s:acceptor p_rec is null", __func__);
+                 break;
+            }
+        }
 
         /* get profile version (if failure, version parameter is not updated) */
         SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_HF_HANDSFREE, &bta_hf_client_cb.scb.peer_version);
@@ -304,8 +318,10 @@
     UINT16          num_uuid = 1;
     UINT16          attr_list[4];
     UINT8           num_attr;
-    BOOLEAN         db_inited = FALSE;
+    BOOLEAN         db_inited_int = FALSE;
+    BOOLEAN         db_inited_acp = FALSE;
 
+    APPL_TRACE_DEBUG("%s: bta_hf_client_cb.scb.role=%d",__func__, bta_hf_client_cb.scb.role);
     /* initiator; get proto list and features */
     if (bta_hf_client_cb.scb.role == BTA_HF_CLIENT_INT)
     {
@@ -315,6 +331,32 @@
         attr_list[3] = ATTR_ID_SUPPORTED_FEATURES;
         num_attr = 4;
         uuid_list[0].uu.uuid16 = UUID_SERVCLASS_AG_HANDSFREE;
+
+        /* allocate buffer for sdp database for initiator */
+        bta_hf_client_cb.scb.p_disc_db_int =
+                       (tSDP_DISCOVERY_DB *)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
+
+        /* set up service discovery database; attr happens to be attr_list len */
+        uuid_list[0].len = LEN_UUID_16;
+        uuid_list[1].len = LEN_UUID_16;
+        db_inited_int = SDP_InitDiscoveryDb(bta_hf_client_cb.scb.p_disc_db_int,
+                                    BT_DEFAULT_BUFFER_SIZE, num_uuid,
+                                    uuid_list, num_attr, attr_list);
+        APPL_TRACE_DEBUG("%s: db_inited_int=%d",__func__, db_inited_int);
+        if (db_inited_int)
+        {
+            /*Service discovery not initiated */
+            db_inited_int = SDP_ServiceSearchAttributeRequest(bta_hf_client_cb.scb.peer_addr,
+                                bta_hf_client_cb.scb.p_disc_db_int, bta_hf_client_sdp_cback);
+        }
+
+        if (!db_inited_int)
+        {
+            /*free discover db */
+            bta_hf_client_free_db_int(NULL);
+            /* sent failed event */
+            bta_hf_client_sm_execute(BTA_HF_CLIENT_DISC_FAIL_EVT, NULL);
+        }
     }
     /* acceptor; get features */
     else
@@ -324,47 +366,64 @@
         attr_list[2] = ATTR_ID_SUPPORTED_FEATURES;
         num_attr = 3;
         uuid_list[0].uu.uuid16 = UUID_SERVCLASS_AG_HANDSFREE;
-    }
 
-    /* allocate buffer for sdp database */
-    bta_hf_client_cb.scb.p_disc_db = (tSDP_DISCOVERY_DB *)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
+        /* allocate buffer for sdp database for acceptor */
+        bta_hf_client_cb.scb.p_disc_db_acp = (tSDP_DISCOVERY_DB *)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
 
-    /* set up service discovery database; attr happens to be attr_list len */
-    uuid_list[0].len = LEN_UUID_16;
-    uuid_list[1].len = LEN_UUID_16;
-    db_inited = SDP_InitDiscoveryDb(bta_hf_client_cb.scb.p_disc_db,
+        /* set up service discovery database; attr happens to be attr_list len */
+        uuid_list[0].len = LEN_UUID_16;
+        uuid_list[1].len = LEN_UUID_16;
+        db_inited_acp = SDP_InitDiscoveryDb(bta_hf_client_cb.scb.p_disc_db_acp,
                                     BT_DEFAULT_BUFFER_SIZE, num_uuid,
                                     uuid_list, num_attr, attr_list);
+        APPL_TRACE_DEBUG("%s: db_inited_acp=%d",__func__, db_inited_acp);
+        if (db_inited_acp)
+        {
+            /*Service discovery not initiated */
+            db_inited_acp = SDP_ServiceSearchAttributeRequest(bta_hf_client_cb.scb.peer_addr,
+                                bta_hf_client_cb.scb.p_disc_db_acp, bta_hf_client_sdp_cback);
+        }
 
-    if (db_inited)
-    {
-        /*Service discovery not initiated */
-        db_inited = SDP_ServiceSearchAttributeRequest(bta_hf_client_cb.scb.peer_addr,
-                            bta_hf_client_cb.scb.p_disc_db, bta_hf_client_sdp_cback);
+        if (!db_inited_acp)
+        {
+            /*free discover db */
+            bta_hf_client_free_db_acp(NULL);
+            /* sent failed event */
+            bta_hf_client_sm_execute(BTA_HF_CLIENT_DISC_FAIL_EVT, NULL);
+        }
     }
-
-    if (!db_inited)
-    {
-        /*free discover db */
-        bta_hf_client_free_db(NULL);
-        /* sent failed event */
-        bta_hf_client_sm_execute(BTA_HF_CLIENT_DISC_FAIL_EVT, NULL);
-    }
-
 }
 
 /*******************************************************************************
 **
-** Function         bta_hf_client_free_db
+** Function         bta_hf_client_free_db_int
 **
-** Description      Free discovery database.
+** Description      Free discovery database of initiator.
 **
 **
 ** Returns          void
 **
 *******************************************************************************/
-void bta_hf_client_free_db(tBTA_HF_CLIENT_DATA *p_data)
+void bta_hf_client_free_db_int(tBTA_HF_CLIENT_DATA *p_data)
 {
     UNUSED(p_data);
-    osi_free_and_reset((void **)&bta_hf_client_cb.scb.p_disc_db);
+    APPL_TRACE_DEBUG("%s:",__func__);
+    osi_free_and_reset((void **)&bta_hf_client_cb.scb.p_disc_db_int);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hf_client_free_db_acp
+**
+** Description      Free discovery database of acceptor.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hf_client_free_db_acp(tBTA_HF_CLIENT_DATA *p_data)
+{
+    UNUSED(p_data);
+    APPL_TRACE_DEBUG("%s:",__func__);
+    osi_free_and_reset((void **)&bta_hf_client_cb.scb.p_disc_db_acp);
 }
diff --git a/bta/hh/bta_hh_act.c b/bta/hh/bta_hh_act.c
index 7d0e5bd..44fbbb5 100644
--- a/bta/hh/bta_hh_act.c
+++ b/bta/hh/bta_hh_act.c
@@ -35,6 +35,7 @@
 #include "bta_hh_int.h"
 #include "bta_hh_co.h"
 #include "utl.h"
+#include "btm_ble_api.h"
 
 /*****************************************************************************
 **  Constants
@@ -105,8 +106,11 @@
     }
     else
 #endif
+    if (bta_hh_cb.p_cback)
+    {
         /* signal BTA call back event */
         (* bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH *)&status);
+    }
 }
 /*******************************************************************************
 **
@@ -400,6 +404,13 @@
         } else {
             status = BTA_HH_OK;
         }
+    } else if (bta_hh_cb.p_disc_db) {
+    /* It is possible that there is incoming/outgoing collision case. DUT initiated
+     * HID connection at same time remote has connected l2cap for HID control,
+     * so SDP would be in progress, when this flow reaches here. Just do nothing
+     * when the code reaches here, and ongoing SDP completion or failure will handle this case */
+        APPL_TRACE_DEBUG ("bta_hh_start_sdp:  ignoring as SDP already in progress");
+        return;
     }
 
     if (status != BTA_HH_OK)
@@ -486,6 +497,7 @@
             APPL_TRACE_DEBUG ("bta_hh_sdp_cmpl:SDP failed for  incoming conn :hndl %d",
                                 p_cb->incoming_hid_handle);
             HID_HostRemoveDev( p_cb->incoming_hid_handle);
+            GENERATE_VENDOR_LOGS();
         }
         conn_dat.status = status;
         (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
@@ -571,6 +583,8 @@
     conn.status = p_cb->status;
     conn.le_hid = p_cb->is_le_device;
     conn.scps_supported = p_cb->scps_supported;
+    if(p_cb->scps_supported)
+        BTA_HhUpdateLeScanParam(dev_handle,BTM_BLE_SCAN_SLOW_INT_1,BTM_BLE_SCAN_SLOW_WIN_1);
 
     if (!p_cb->is_le_device)
 #endif
@@ -593,6 +607,7 @@
             /* HID connection is up, while SET_PROTO fail */
             conn.status = BTA_HH_ERR_PROTO;
             (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn);
+            GENERATE_VENDOR_LOGS();
         }
         else
         {
@@ -676,7 +691,7 @@
 **
 ** Function         bta_hh_handsk_act
 **
-** Description      HID Host process a handshake acknoledgement.
+** Description      HID Host process a handshake acknowledgement.
 **
 **
 ** Returns          void
@@ -708,7 +723,8 @@
             /* if handshake gives an OK code for these transaction, fill in UNSUPT */
             if ((hs_data.status = bta_hh_get_trans_status(p_data->hid_cback.data)) == BTA_HH_OK)
                  hs_data.status = BTA_HH_HS_TRANS_NOT_SPT;
-
+            if (p_cb->w4_evt == BTA_HH_GET_RPT_EVT)
+                bta_hh_co_get_rpt_rsp(cback_data.handle, hs_data.status, NULL, 0);
             (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&hs_data);
             p_cb->w4_evt = 0;
             break;
@@ -719,6 +735,8 @@
         case BTA_HH_SET_IDLE_EVT :
             cback_data.handle  = p_cb->hid_handle;
             cback_data.status = bta_hh_get_trans_status(p_data->hid_cback.data);
+            if (p_cb->w4_evt == BTA_HH_SET_RPT_EVT)
+                bta_hh_co_set_rpt_rsp(cback_data.handle, cback_data.status);
             (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&cback_data);
             p_cb->w4_evt = 0;
             break;
@@ -781,6 +799,7 @@
         break;
     case BTA_HH_GET_RPT_EVT:
         hs_data.rsp_data.p_rpt_data = pdata;
+        bta_hh_co_get_rpt_rsp(hs_data.handle, hs_data.status, pdata->data, pdata->len);
         break;
     case BTA_HH_GET_PROTO_EVT:
         /* match up BTE/BTA report/boot mode def*/
@@ -834,14 +853,26 @@
     UINT32                  reason = p_data->hid_cback.data;    /* Reason for closing (32-bit) */
 
     memset(&conn_dat, 0, sizeof(tBTA_HH_CONN));
-     conn_dat.handle = p_cb->hid_handle;
-     conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ?
+    conn_dat.handle = p_cb->hid_handle;
+    conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ?
                                     BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
-     bdcpy(conn_dat.bda, p_cb->addr);
-     HID_HostCloseDev(p_cb->hid_handle);
+    bdcpy(conn_dat.bda, p_cb->addr);
+    HID_HostCloseDev(p_cb->hid_handle);
+    GENERATE_VENDOR_LOGS();
 
-     /* Report OPEN fail event */
-     (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG("bta_hh_open_failure: hid_handle = %d", p_cb->hid_handle);
+#endif
+
+    /* Report OPEN fail event */
+    (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
+
+    /* if virtually unplug, remove device */
+    if (p_cb->vp )
+    {
+        HID_HostRemoveDev( p_cb->hid_handle);
+        bta_hh_clean_up_kdev(p_cb);
+    }
 
 #if BTA_HH_DEBUG
     bta_hh_trace_dev_db();
@@ -880,6 +911,10 @@
     /* if HID_HDEV_EVT_VC_UNPLUG was received, report BTA_HH_VC_UNPLUG_EVT */
     UINT16     event = p_cb->vp ? BTA_HH_VC_UNPLUG_EVT : BTA_HH_CLOSE_EVT;
 
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG("bta_hh_close_act: reason = %d", reason);
+#endif
+
     disc_dat.handle = p_cb->hid_handle;
     disc_dat.status = p_data->hid_cback.data;
 
@@ -892,10 +927,13 @@
         conn_dat.handle = p_cb->hid_handle;
         conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
         bdcpy(conn_dat.bda, p_cb->addr);
+        /* finalize device driver */
+        bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
         HID_HostCloseDev(p_cb->hid_handle);
 
         /* Report OPEN fail event */
         (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
+        GENERATE_VENDOR_LOGS();
 
 #if BTA_HH_DEBUG
         bta_hh_trace_dev_db();
@@ -905,7 +943,7 @@
     /* otherwise report CLOSE/VC_UNPLUG event */
     else
     {
-        /* finaliza device driver */
+        /* finalize device driver */
         bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
         /* inform role manager */
         bta_sys_conn_close( BTA_ID_HH ,p_cb->app_id, p_cb->addr);
@@ -1166,7 +1204,7 @@
         }
         else if (p_data->api_sndcmd.param == BTA_HH_CTRL_SUSPEND)
         {
-			bta_sys_sco_close(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+            bta_sys_sco_close(BTA_ID_HH, p_cb->app_id, p_cb->addr);
         }
         else if (p_data->api_sndcmd.param == BTA_HH_CTRL_EXIT_SUSPEND)
         {
@@ -1234,6 +1272,20 @@
                break;
             }
         }
+        if (xx == BTA_HH_MAX_DEVICE)
+        {
+            for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++)
+            {
+                /* No device matched entry for VC, check if VC receivied in waitng for conn state */
+                APPL_TRACE_DEBUG("bta_hh_cb.kdev[xx].state = %d", bta_hh_cb.kdev[xx].state);
+                if (bta_hh_cb.kdev[xx].state == BTA_HH_W4_CONN_ST)
+                {
+                   bta_hh_cb.kdev[xx].hid_handle = dev_handle;
+                   bta_hh_cb.kdev[xx].vp = TRUE;
+                   break;
+                }
+            }
+        }
         break;
     }
 
diff --git a/bta/hh/bta_hh_int.h b/bta/hh/bta_hh_int.h
index ba5eb0e..ecfad54 100644
--- a/bta/hh/bta_hh_int.h
+++ b/bta/hh/bta_hh_int.h
@@ -222,6 +222,14 @@
 
 }tBTA_HH_LE_HID_SRVC;
 
+#ifndef BTA_HH_LE_HID_SRVC_MAX
+#if (defined(BLE_HH_QUALIFICATION_ENABLED) && BLE_HH_QUALIFICATION_ENABLED == TRUE)
+#define BTA_HH_LE_HID_SRVC_MAX      2
+#else
+#define BTA_HH_LE_HID_SRVC_MAX      1
+#endif
+#endif
+
 /* convert a HID handle to the LE CB index */
 #define BTA_HH_GET_LE_CB_IDX(x)         (((x) >> 4) - 1)
 /* convert a GATT connection ID to HID device handle, it is the hi 4 bits of a UINT8 */
@@ -262,11 +270,14 @@
     tBTA_HH_STATUS      status;
     tBTA_GATT_REASON    reason;
     BOOLEAN             is_le_device;
-    tBTA_HH_LE_HID_SRVC hid_srvc;
+    UINT8               total_srvc;
+    tBTA_HH_LE_HID_SRVC hid_srvc[BTA_HH_LE_HID_SRVC_MAX];
     UINT16              conn_id;
     BOOLEAN             in_bg_conn;
+    UINT8               cur_srvc_index; /* currently discovering service index */
     UINT8               clt_cfg_idx;
     UINT16              scan_refresh_char_handle;
+    UINT16              scan_int_char_handle;
     BOOLEAN             scps_supported;
 
 #define BTA_HH_LE_SCPS_NOTIFY_NONE    0
diff --git a/bta/hh/bta_hh_le.c b/bta/hh/bta_hh_le.c
index 75d6bd3..af7b74c 100644
--- a/bta/hh/bta_hh_le.c
+++ b/bta/hh/bta_hh_le.c
@@ -31,9 +31,9 @@
 #include "btm_api.h"
 #include "btm_ble_api.h"
 #include "btm_int.h"
+#include "device/include/interop.h"
 #include "osi/include/log.h"
 #include "srvc_api.h"
-#include "stack/include/l2c_api.h"
 #include "utl.h"
 
 #ifndef BTA_HH_LE_RECONN
@@ -243,37 +243,50 @@
 *******************************************************************************/
 static void bta_hh_le_hid_report_dbg(tBTA_HH_DEV_CB *p_cb)
 {
+    UINT8 i, j;
+    tBTA_HH_LE_RPT *p_rpt;
+    char *rpt_name;
+
     APPL_TRACE_DEBUG("%s: HID Report DB", __func__);
 
-    if (!p_cb->hid_srvc.in_use)
-        return;
-
-    tBTA_HH_LE_RPT  *p_rpt = &p_cb->hid_srvc.report[0];
-
-    for (int j = 0; j < BTA_HH_LE_RPT_MAX; j ++, p_rpt++)
+    for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++)
     {
-        char *  rpt_name = "Unknown";
+        if (p_cb->hid_srvc[i].in_use)
+        {
+            p_rpt = &p_cb->hid_srvc[i].report[0];
 
-        if (!p_rpt->in_use)
+            APPL_TRACE_DEBUG("\t HID serivce inst: %d", i);
+
+            for (j = 0; j < BTA_HH_LE_RPT_MAX; j ++, p_rpt++)
+            {
+                rpt_name = "Unknown";
+                if (p_rpt->in_use)
+                {
+                    if (p_rpt->uuid == GATT_UUID_HID_REPORT)
+                        rpt_name = "Report";
+                    if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT)
+                        rpt_name = "Boot KB Input";
+                    if (p_rpt->uuid == GATT_UUID_HID_BT_KB_OUTPUT)
+                        rpt_name = "Boot KB Output";
+                    if (p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT)
+                        rpt_name = "Boot MI Input";
+
+                   APPL_TRACE_DEBUG("\t\t [%s- 0x%04x] [Type: %s], [ReportID: %d] [srvc_inst_id: %d] [char_inst_id: %d] [Clt_cfg: %d]",
+                         rpt_name,
+                         p_rpt->uuid ,
+                         ((p_rpt->rpt_type < 4) ? bta_hh_le_rpt_name[p_rpt->rpt_type]
+                         : "UNKNOWN"),
+                         p_rpt->rpt_id,
+                         p_rpt->srvc_inst_id,
+                         p_rpt->char_inst_id,
+                         p_rpt->client_cfg_value);
+                }
+                else
+                    break;
+            }
+        }
+        else
             break;
-
-        if (p_rpt->uuid == GATT_UUID_HID_REPORT)
-            rpt_name = "Report";
-        if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT)
-            rpt_name = "Boot KB Input";
-        if (p_rpt->uuid == GATT_UUID_HID_BT_KB_OUTPUT)
-            rpt_name = "Boot KB Output";
-        if (p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT)
-            rpt_name = "Boot MI Input";
-
-        APPL_TRACE_DEBUG("\t\t [%s- 0x%04x] [Type: %s], [ReportID: %d] [srvc_inst_id: %d] [char_inst_id: %d] [Clt_cfg: %d]",
-            rpt_name,
-            p_rpt->uuid ,
-            ((p_rpt->rpt_type < 4) ? bta_hh_le_rpt_name[p_rpt->rpt_type] : "UNKNOWN"),
-            p_rpt->rpt_id,
-            p_rpt->srvc_inst_id,
-            p_rpt->char_inst_id,
-            p_rpt->client_cfg_value);
     }
 }
 
@@ -490,10 +503,15 @@
 *******************************************************************************/
 UINT8 bta_hh_le_find_service_inst_by_battery_inst_id(tBTA_HH_DEV_CB *p_cb, UINT8 ba_inst_id)
 {
-    if (p_cb->hid_srvc.in_use &&
-        p_cb->hid_srvc.incl_srvc_inst == ba_inst_id)
+    UINT8   srvc_inst_id;
+
+    for (srvc_inst_id = 0; srvc_inst_id < BTA_HH_LE_HID_SRVC_MAX; srvc_inst_id ++)
     {
-        return p_cb->hid_srvc.srvc_inst_id;
+        if (p_cb->hid_srvc[srvc_inst_id].in_use &&
+            p_cb->hid_srvc[srvc_inst_id].incl_srvc_inst == ba_inst_id)
+        {
+            return srvc_inst_id;
+        }
     }
     return BTA_HH_IDX_INVALID;
 }
@@ -511,7 +529,7 @@
                                              UINT16 rpt_uuid,
                                              UINT8  char_inst_id)
 {
-    UINT8   i;
+    UINT8   i,j;
     UINT8   hid_inst_id = srvc_inst_id;
     tBTA_HH_LE_RPT *p_rpt;
 
@@ -523,16 +541,19 @@
             return NULL;
     }
 
-    p_rpt = &p_cb->hid_srvc.report[0];
-
-    for (i = 0; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt ++)
+    for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++)
     {
-        if (p_rpt->uuid == rpt_uuid &&
-            p_rpt->srvc_inst_id == srvc_inst_id &&
-            p_rpt->char_inst_id == char_inst_id)
-        {
+        p_rpt = &p_cb->hid_srvc[i].report[0];
 
-            return p_rpt;
+        for (j = 0; j < BTA_HH_LE_RPT_MAX; j ++, p_rpt ++)
+        {
+            if (p_rpt->uuid == rpt_uuid &&
+                p_rpt->srvc_inst_id == srvc_inst_id &&
+                p_rpt->char_inst_id == char_inst_id)
+            {
+
+                return p_rpt;
+            }
         }
     }
     return NULL;
@@ -599,7 +620,7 @@
         if (hid_inst_id == BTA_HH_IDX_INVALID)
             return NULL;
     }
-    p_rpt = &p_cb->hid_srvc.report[0];
+    p_rpt = &p_cb->hid_srvc[p_cb->cur_srvc_index].report[0];
 
     for (i = 0; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt ++)
     {
@@ -752,11 +773,11 @@
     if (p_data->status == BTA_GATT_OK &&
         p_data->p_value && p_data->p_value->len == 2) {
         UINT8 *pp = p_data->p_value->p_value;
-        STREAM_TO_UINT16(p_dev_cb->hid_srvc.ext_rpt_ref, pp);
+        STREAM_TO_UINT16(p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].ext_rpt_ref, pp);
 
 #if BTA_HH_DEBUG == TRUE
         APPL_TRACE_DEBUG("%s: External Report Reference UUID 0x%04x", __func__,
-                    p_dev_cb->hid_srvc.ext_rpt_ref);
+                    p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].ext_rpt_ref);
 #endif
     }
 }
@@ -771,9 +792,10 @@
 ** Parameters:
 **
 *******************************************************************************/
-void bta_hh_le_register_input_notif(tBTA_HH_DEV_CB *p_dev_cb, UINT8 proto_mode, BOOLEAN register_ba)
+void bta_hh_le_register_input_notif(tBTA_HH_DEV_CB *p_dev_cb, UINT8 srvc_inst,
+                                    UINT8 proto_mode, BOOLEAN register_ba)
 {
-    tBTA_HH_LE_RPT  *p_rpt = &p_dev_cb->hid_srvc.report[0];
+    tBTA_HH_LE_RPT  *p_rpt = &p_dev_cb->hid_srvc[srvc_inst].report[0];
 
 #if BTA_HH_DEBUG == TRUE
     APPL_TRACE_DEBUG("%s: bta_hh_le_register_input_notif mode: %d", __func__, proto_mode);
@@ -842,7 +864,8 @@
 *******************************************************************************/
 void bta_hh_le_deregister_input_notif(tBTA_HH_DEV_CB *p_dev_cb)
 {
-    tBTA_HH_LE_RPT  *p_rpt = &p_dev_cb->hid_srvc.report[0];
+    tBTA_HH_LE_RPT  *p_rpt = &p_dev_cb->hid_srvc[0].report[0];
+    APPL_TRACE_DEBUG("%s ---> current service instance:%d", __func__, p_dev_cb->cur_srvc_index);
 
     for (UINT8 i = 0; i < BTA_HH_LE_RPT_MAX; i++, p_rpt++)
     {
@@ -882,7 +905,7 @@
 #if BTA_HH_DEBUG
         bta_hh_le_hid_report_dbg(p_cb);
 #endif
-        bta_hh_le_register_input_notif(p_cb, p_cb->mode, TRUE);
+        bta_hh_le_register_input_notif(p_cb, 0, p_cb->mode, TRUE);
         bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
 
 #if (BTA_HH_LE_RECONN == TRUE)
@@ -930,13 +953,15 @@
 BOOLEAN bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst_id)
 {
     UINT8           i;
-    tBTA_HH_LE_RPT  *p_rpt = &p_cb->hid_srvc.report[p_cb->clt_cfg_idx];
+    tBTA_HH_LE_RPT  *p_rpt = &p_cb->hid_srvc[srvc_inst_id].report[p_cb->clt_cfg_idx];
 
     for (i = p_cb->clt_cfg_idx; i < BTA_HH_LE_RPT_MAX && p_rpt->in_use; i ++, p_rpt ++)
     {
         /* enable notification for all input report, regardless mode */
         if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
         {
+            p_cb->cur_srvc_index = srvc_inst_id;
+            APPL_TRACE_DEBUG(" %s  service instance :%d", __func__, srvc_inst_id);
             if (bta_hh_le_write_char_clt_cfg(p_cb,
                                              p_rpt->char_inst_id,
                                              BTA_GATT_CLT_CONFIG_NOTIFICATION))
@@ -947,13 +972,19 @@
         }
     }
     p_cb->clt_cfg_idx = 0;
-
+    p_cb->cur_srvc_index++;
+    if (p_cb->cur_srvc_index < BTA_HH_LE_HID_SRVC_MAX)
+    {
+        bta_hh_le_write_rpt_clt_cfg(p_cb,p_cb->cur_srvc_index);
+        return TRUE;
+    }
     /* client configuration is completed, send open callback */
     if (p_cb->state == BTA_HH_W4_CONN_ST)
     {
         p_cb->disc_active &= ~BTA_HH_LE_DISC_HIDS;
 
         bta_hh_le_open_cmpl(p_cb);
+        p_cb->cur_srvc_index = 0;
     }
     return FALSE;
 }
@@ -975,7 +1006,7 @@
 
     cback_data.handle  = p_cb->hid_handle;
     /* boot mode is not supported in the remote device */
-    if (p_cb->hid_srvc.proto_mode_handle == 0)
+    if (p_cb->hid_srvc[p_cb->cur_srvc_index].proto_mode_handle == 0)
     {
         p_cb->mode  = BTA_HH_PROTO_RPT_MODE;
 
@@ -987,7 +1018,7 @@
         else
         {
             /* if set to report mode, need to de-register all input report notification */
-            bta_hh_le_register_input_notif(p_cb, p_cb->mode, FALSE);
+            bta_hh_le_register_input_notif(p_cb, 0, p_cb->mode, FALSE);
             cback_data.status = BTA_HH_OK;
         }
         if (p_cb->state == BTA_HH_W4_CONN_ST)
@@ -1000,7 +1031,7 @@
         p_cb->mode = mode;
         mode = (mode == BTA_HH_PROTO_BOOT_MODE)? BTA_HH_LE_PROTO_BOOT_MODE : BTA_HH_LE_PROTO_REPORT_MODE;
 
-        gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id, p_cb->hid_srvc.proto_mode_handle, 1,
+        gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id, p_cb->hid_srvc[p_cb->cur_srvc_index].proto_mode_handle, 1,
                             &mode, BTA_GATTC_TYPE_WRITE_NO_RSP);
         exec        = TRUE;
     }
@@ -1018,19 +1049,25 @@
 void bta_hh_le_get_protocol_mode(tBTA_HH_DEV_CB *p_cb)
 {
     tBTA_HH_HSDATA    hs_data;
+    int i;
     p_cb->w4_evt = BTA_HH_GET_PROTO_EVT;
-
-    if (p_cb->hid_srvc.in_use && p_cb->hid_srvc.proto_mode_handle != 0) {
-        gatt_queue_read_op(GATT_READ_CHAR, p_cb->conn_id, p_cb->hid_srvc.proto_mode_handle);
-        return;
+    for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++)
+    {
+        if (p_cb->hid_srvc[i].in_use && p_cb->hid_srvc[i].proto_mode_handle != 0) {
+           gatt_queue_read_op(GATT_READ_CHAR, p_cb->conn_id, p_cb->hid_srvc[i].proto_mode_handle);
+           break;
+        }
     }
 
     /* no service support protocol_mode, by default report mode */
-    hs_data.status  = BTA_HH_OK;
-    hs_data.handle  = p_cb->hid_handle;
-    hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
-    p_cb->w4_evt = 0;
-    (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
+    if (i == BTA_HH_LE_HID_SRVC_MAX)
+    {
+        hs_data.status  = BTA_HH_OK;
+        hs_data.handle  = p_cb->hid_handle;
+        hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
+        p_cb->w4_evt = 0;
+        (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
+    }
 }
 
 /*******************************************************************************
@@ -1150,7 +1187,7 @@
     APPL_TRACE_DEBUG("%s", __func__);
     if (p_cb->status == BTA_HH_OK)
     {
-        if (!p_cb->hid_srvc.in_use)
+        if (!p_cb->hid_srvc[0].in_use)
         {
             APPL_TRACE_DEBUG("bta_hh_security_cmpl no reports loaded, try to load");
 
@@ -1164,7 +1201,7 @@
             // }
         }
         /*  discovery has been done for HID service */
-        if (p_cb->app_id != 0 && p_cb->hid_srvc.in_use)
+        if (p_cb->app_id != 0 && p_cb->hid_srvc[0].in_use)
         {
             APPL_TRACE_DEBUG("%s: discovery has been done for HID service", __func__);
             /* configure protocol mode */
@@ -1221,13 +1258,18 @@
 *******************************************************************************/
 void bta_hh_clear_service_cache(tBTA_HH_DEV_CB *p_cb)
 {
-    tBTA_HH_LE_HID_SRVC     *p_hid_srvc = &p_cb->hid_srvc;
+    UINT8 i;
+    tBTA_HH_LE_HID_SRVC     *p_hid_srvc = &p_cb->hid_srvc[0];
 
     p_cb->app_id = 0;
+    p_cb->total_srvc = 0;
     p_cb->dscp_info.descriptor.dsc_list = NULL;
 
-    osi_free_and_reset((void **)&p_hid_srvc->rpt_map);
-    memset(p_hid_srvc, 0, sizeof(tBTA_HH_LE_HID_SRVC));
+    for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++, p_hid_srvc ++)
+    {
+        osi_free_and_reset((void **)&p_hid_srvc->rpt_map);
+        memset(p_hid_srvc, 0, sizeof(tBTA_HH_LE_HID_SRVC));
+    }
 }
 
 /*******************************************************************************
@@ -1320,6 +1362,7 @@
         p_cb->in_use    = TRUE;
         p_cb->conn_id   = p_data->conn_id;
         p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
+        p_cb->cur_srvc_index = 0;
 
         bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
 
@@ -1379,7 +1422,7 @@
 *******************************************************************************/
 void bta_hh_le_gatt_disc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_STATUS status)
 {
-    APPL_TRACE_DEBUG("bta_hh_le_gatt_disc_cmpl ");
+    APPL_TRACE_DEBUG("%s srvc_index =%d ", __func__, p_cb->cur_srvc_index);
 
     /* if open sucessful or protocol mode not desired, keep the connection open but inform app */
     if (status == BTA_HH_OK || status == BTA_HH_ERR_PROTO)
@@ -1389,7 +1432,7 @@
 
         /* set report notification configuration */
         p_cb->clt_cfg_idx = 0;
-        bta_hh_le_write_rpt_clt_cfg(p_cb, p_cb->hid_srvc.srvc_inst_id);
+        bta_hh_le_write_rpt_clt_cfg(p_cb, 0);
     }
     else /* error, close the GATT connection */
     {
@@ -1398,7 +1441,7 @@
     }
 }
 
-void process_included(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_SERVICE *service) {
+void process_included(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_SERVICE *service, int srvc_index) {
     if (!service->included_svc || list_is_empty(service->included_svc)) {
         APPL_TRACE_ERROR("%s: Remote device does not have battery level", __func__);
         return;
@@ -1412,7 +1455,7 @@
             incl_svc->uuid.len == LEN_UUID_16) {
 
             /* read include service UUID */
-            p_dev_cb->hid_srvc.incl_srvc_inst = incl_svc->handle;
+            p_dev_cb->hid_srvc[srvc_index].incl_srvc_inst = incl_svc->handle;
 
             for (list_node_t *cn = list_begin(incl_svc->characteristics);
                  cn != list_end(incl_svc->characteristics); cn = list_next(cn)) {
@@ -1463,7 +1506,7 @@
         switch (p_char->uuid.uu.uuid16)
         {
         case GATT_UUID_HID_CONTROL_POINT:
-            p_dev_cb->hid_srvc.control_point_handle = p_char->handle;
+            p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].control_point_handle = p_char->handle;
             break;
         case GATT_UUID_HID_INFORMATION:
         case GATT_UUID_HID_REPORT_MAP:
@@ -1476,7 +1519,7 @@
 
         case GATT_UUID_HID_REPORT:
             p_rpt = bta_hh_le_find_alloc_report_entry(p_dev_cb,
-                                              p_dev_cb->hid_srvc.srvc_inst_id,
+                                              p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].srvc_inst_id,
                                               GATT_UUID_HID_REPORT,
                                               p_char->handle);
             if (p_rpt == NULL) {
@@ -1516,7 +1559,7 @@
 
         if(p_char->uuid.len != LEN_UUID_16 &&
            p_char->uuid.uu.uuid16 == GATT_UUID_HID_PROTO_MODE) {
-            p_dev_cb->hid_srvc.proto_mode_handle = p_char->handle;
+            p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].proto_mode_handle = p_char->handle;
             bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode);
             break;
         }
@@ -1535,6 +1578,7 @@
 void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL *p_data)
 {
     tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
+    int srvc_index = 0;
 
     /* service search exception or no HID service is supported on remote */
     if (p_dev_cb == NULL)
@@ -1556,22 +1600,43 @@
         tBTA_GATTC_SERVICE *service = list_node(sn);
 
         if (service->uuid.uu.uuid16 == UUID_SERVCLASS_LE_HID &&
-            service->is_primary && !have_hid) {
+            service->is_primary ) {
             have_hid = true;
-
             /* found HID primamry service */
-            p_dev_cb->hid_srvc.in_use = TRUE;
-            p_dev_cb->hid_srvc.srvc_inst_id = service->handle;
-            p_dev_cb->hid_srvc.proto_mode_handle = 0;
-            p_dev_cb->hid_srvc.control_point_handle = 0;
-
-            process_included(p_dev_cb, service);
+            srvc_index = p_dev_cb->cur_srvc_index;
+            p_dev_cb->hid_srvc[srvc_index].in_use = TRUE;
+            p_dev_cb->hid_srvc[srvc_index].srvc_inst_id = service->handle;
+            p_dev_cb->hid_srvc[srvc_index].proto_mode_handle = 0;
+            p_dev_cb->hid_srvc[srvc_index].control_point_handle = 0;
+            process_included(p_dev_cb, service,srvc_index);
             bta_hh_le_search_hid_chars(p_dev_cb, service);
 
-            APPL_TRACE_DEBUG("%s: have HID service inst_id= %d", __func__, p_dev_cb->hid_srvc.srvc_inst_id);
+            APPL_TRACE_DEBUG("%s: have HID service inst_id= %d", __func__, p_dev_cb->hid_srvc[srvc_index].srvc_inst_id);
+            if (p_dev_cb->cur_srvc_index < BTA_HH_LE_HID_SRVC_MAX-1)
+                p_dev_cb->cur_srvc_index++;
+        } else if (service->uuid.uu.uuid16 == UUID_SERVCLASS_BATTERY) {
+            for (list_node_t *cn = list_begin(service->characteristics);
+                 cn != list_end(service->characteristics); cn = list_next(cn)) {
+                tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
+                if (p_char->uuid.uu.uuid16 == GATT_UUID_BATTERY_LEVEL &&
+                    p_char->uuid.len == LEN_UUID_16) {
+
+                    if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
+                                                          service->s_handle,
+                                                          GATT_UUID_BATTERY_LEVEL,
+                                                          p_char->handle) == NULL)
+                        APPL_TRACE_ERROR("Add battery report entry failed !!!");
+
+                    gatt_queue_read_op(GATT_READ_CHAR, p_dev_cb->conn_id, p_char->handle);
+                    APPL_TRACE_DEBUG("%s: battery service handle= %d", __func__, p_char->handle);
+                    bta_hh_le_read_char_dscrpt(p_dev_cb, p_char->handle,
+                                             GATT_UUID_CHAR_CLIENT_CONFIG);
+                }
+            }
         } else if (service->uuid.uu.uuid16 == UUID_SERVCLASS_SCAN_PARAM) {
             p_dev_cb->scan_refresh_char_handle = 0;
-
+            p_dev_cb->scan_int_char_handle  = 0;
+            p_dev_cb->scps_supported = TRUE;
             for (list_node_t *cn = list_begin(service->characteristics);
                  cn != list_end(service->characteristics); cn = list_next(cn)) {
                 tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
@@ -1585,22 +1650,13 @@
                     else
                         p_dev_cb->scps_notify = BTA_HH_LE_SCPS_NOTIFY_NONE;
 
-                    break;
                 }
-            }
-        } else if (service->uuid.uu.uuid16 == UUID_SERVCLASS_GAP_SERVER) {
-            //TODO(jpawlowski): this should be done by GAP profile, remove when GAP is fixed.
-            for (list_node_t *cn = list_begin(service->characteristics);
-                 cn != list_end(service->characteristics); cn = list_next(cn)) {
-                tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
                 if (p_char->uuid.len == LEN_UUID_16 &&
-                    p_char->uuid.uu.uuid16 == GATT_UUID_GAP_PREF_CONN_PARAM) {
-
-                    /* read the char value */
-                    gatt_queue_read_op(GATT_READ_CHAR, p_dev_cb->conn_id, p_char->handle);
-
-                    break;
-                }
+                    p_char->uuid.uu.uuid16 == GATT_UUID_SCAN_INT_WINDOW) {
+                    p_dev_cb->scan_int_char_handle = p_char->handle;
+               }
+               if (p_dev_cb->scan_refresh_char_handle &&  p_dev_cb->scan_int_char_handle)
+                   break;
             }
         }
     }
@@ -1621,7 +1677,7 @@
 {
     UNUSED(status);
     UNUSED(p_data);
-    p_dev_cb->hid_srvc.expl_incl_srvc = TRUE;
+    p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc = TRUE;
 }
 
 
@@ -1636,7 +1692,7 @@
 *******************************************************************************/
 void bta_hh_le_save_rpt_map(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
 {
-    tBTA_HH_LE_HID_SRVC *p_srvc = &p_dev_cb->hid_srvc;
+    tBTA_HH_LE_HID_SRVC *p_srvc = &p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index];
 
     osi_free_and_reset((void **)&p_srvc->rpt_map);
 
@@ -1648,7 +1704,7 @@
         UINT8 *pp = p_data->p_value->p_value;
         STREAM_TO_ARRAY(p_srvc->rpt_map, pp, p_data->p_value->len);
         p_srvc->descriptor.dl_len = p_data->p_value->len;
-        p_srvc->descriptor.dsc_list = p_dev_cb->hid_srvc.rpt_map;
+        p_srvc->descriptor.dsc_list = p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].rpt_map;
     }
 }
 
@@ -1678,6 +1734,12 @@
     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
                                                                           p_data->handle);
 
+    if (p_char == NULL) {
+        APPL_TRACE_ERROR("%s: report cmpl for Unknown Characteristic,handle: 0x%04x",
+            __func__, p_data->handle);
+        return;
+    }
+
     memset(&hs_data, 0, sizeof(hs_data));
     hs_data.status  = BTA_HH_ERR;
     hs_data.handle  = p_dev_cb->hid_handle;
@@ -1778,35 +1840,6 @@
     {
         bta_hh_read_battery_level_cmpl(p_data->status, p_dev_cb, p_data);
     }
-    else if (char_uuid == GATT_UUID_GAP_PREF_CONN_PARAM)
-    {
-        //TODO(jpawlowski): this should be done by GAP profile, remove when GAP is fixed.
-        if (p_data->status != BTA_GATT_OK || p_data->p_value == NULL) {
-            APPL_TRACE_ERROR("%s: read pref conn params error: %d",
-                             __func__, p_data->status);
-            return;
-        }
-
-        UINT8 *pp = p_data->p_value->p_value;
-        UINT16 min, max, latency, tout;
-        STREAM_TO_UINT16 (min, pp);
-        STREAM_TO_UINT16 (max, pp);
-        STREAM_TO_UINT16 (latency, pp);
-        STREAM_TO_UINT16 (tout, pp);
-
-        // Make sure both min, and max are bigger than 11.25ms, lower values can introduce
-        // audio issues if A2DP is also active.
-        if (min < BTM_BLE_CONN_INT_MIN_LIMIT)
-            min = BTM_BLE_CONN_INT_MIN_LIMIT;
-        if (max < BTM_BLE_CONN_INT_MIN_LIMIT)
-            max = BTM_BLE_CONN_INT_MIN_LIMIT;
-
-        if (tout < BTM_BLE_CONN_TIMEOUT_MIN_DEF)
-            tout = BTM_BLE_CONN_TIMEOUT_MIN_DEF;
-
-        BTM_BleSetPrefConnParams (p_dev_cb->addr, min, max, latency, tout);
-        L2CA_UpdateBleConnParams(p_dev_cb->addr, min, max, latency, tout);
-    }
     else
     {
         if (p_data->status == BTA_GATT_OK && p_data->p_value)
@@ -2006,6 +2039,11 @@
 
     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
                                                                           p_data->handle);
+    if (p_char == NULL) {
+        APPL_TRACE_ERROR("%s: write cmpl for Unknown Characteristic,handle: 0x%04x",
+            __func__, p_data->handle);
+        return;
+    }
 
     if (p_char->uuid.uu.uuid16 == GATT_UUID_HID_PROTO_MODE)
     {
@@ -2037,6 +2075,12 @@
     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
                                                                           p_data->handle);
 
+    if (p_char == NULL) {
+        APPL_TRACE_ERROR("%s: write cmpl for Unknown Characteristic,handle: 0x%04x",
+            __func__, p_data->handle);
+        return;
+    }
+
 #if BTA_HH_DEBUG
     APPL_TRACE_DEBUG("bta_hh_le_write_cmpl w4_evt: %d", p_dev_cb->w4_evt);
 #endif
@@ -2047,7 +2091,7 @@
         cback_data.handle  = p_dev_cb->hid_handle;
         if (p_data->status == BTA_GATT_OK)
         {
-            bta_hh_le_register_input_notif(p_dev_cb, p_dev_cb->mode, FALSE);
+            bta_hh_le_register_input_notif(p_dev_cb, p_dev_cb->cur_srvc_index, p_dev_cb->mode, FALSE);
             cback_data.status = BTA_HH_OK;
         }
         else
@@ -2089,8 +2133,8 @@
 void bta_hh_le_write_char_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
 {
     tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
-    UINT8   srvc_inst_id, hid_inst_id;
-
+    UINT8   srvc_inst_id;
+    UINT8 hid_inst_id = 0;
     const tBTA_GATTC_DESCRIPTOR *p_desc = BTA_GATTC_GetDescriptor(p_dev_cb->conn_id,
                                                                        p_data->handle);
 
@@ -2100,7 +2144,6 @@
     if (desc_uuid == GATT_UUID_CHAR_CLIENT_CONFIG)
     {
         srvc_inst_id = p_desc->characteristic->service->handle;
-        hid_inst_id = srvc_inst_id;
         switch (char_uuid)
         {
         case GATT_UUID_BATTERY_LEVEL: /* battery level clt cfg registered */
@@ -2110,11 +2153,14 @@
         case GATT_UUID_HID_BT_MOUSE_INPUT:
         case GATT_UUID_HID_REPORT:
             if (p_data->status == BTA_GATT_OK)
-                p_dev_cb->hid_srvc.report[p_dev_cb->clt_cfg_idx].client_cfg_value =
+                p_dev_cb->hid_srvc[hid_inst_id].report[p_dev_cb->clt_cfg_idx].client_cfg_value =
                         BTA_GATT_CLT_CONFIG_NOTIFICATION;
             p_dev_cb->clt_cfg_idx ++;
-            bta_hh_le_write_rpt_clt_cfg(p_dev_cb, hid_inst_id);
-
+            hid_inst_id = p_dev_cb->cur_srvc_index;
+            if (hid_inst_id < BTA_HH_LE_HID_SRVC_MAX ) {
+                APPL_TRACE_DEBUG("write rpt clt cfg for hid srvc instance: %d", hid_inst_id);
+                bta_hh_le_write_rpt_clt_cfg(p_dev_cb, hid_inst_id);
+            }
             break;
 
         case GATT_UUID_SCAN_REFRESH:
@@ -2169,10 +2215,21 @@
         return;
     }
 
+    if (p_char == NULL) {
+        APPL_TRACE_ERROR("%s: notification received for Unknown Characteristic,handle: 0x%04x",
+            __func__, p_data->handle);
+        return;
+    }
     app_id= p_dev_cb->app_id;
 
+    if (p_char->uuid.uu.uuid16 == GATT_UUID_SCAN_REFRESH) {
+        APPL_TRACE_DEBUG("Notification received for scan refresh parameters");
+        BTA_HhUpdateLeScanParam(p_dev_cb->hid_handle,BTM_BLE_SCAN_SLOW_INT_1,
+                                             BTM_BLE_SCAN_SLOW_WIN_1);
+       return;
+    }
     p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
-                                        p_dev_cb->hid_srvc.srvc_inst_id,
+                                        p_dev_cb->hid_srvc[0].srvc_inst_id,
                                         p_char->uuid.uu.uuid16,
                                         p_char->handle);
     if (p_rpt == NULL)
@@ -2324,15 +2381,31 @@
 ** Returns          void
 **
 *******************************************************************************/
-void bta_hh_le_get_rpt(tBTA_HH_DEV_CB *p_cb, tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id)
+void bta_hh_le_get_rpt(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst, tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id)
 {
-    tBTA_HH_LE_RPT  *p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc.report, p_cb->mode, r_type, rpt_id);
-
+    tBTA_HH_LE_RPT  *p_rpt;
+#if (defined BLE_HH_QUALIFICATION_ENABLED && BLE_HH_QUALIFICATION_ENABLED == TRUE)
+    UINT8  char_handle;
+    switch (rpt_id) {
+        case 7:
+            APPL_TRACE_DEBUG("bta_hh_le_get_rpt: read hid input client confg char ");
+            bta_hh_le_hid_read_rpt_clt_cfg(p_cb->addr, srvc_inst);
+            return;
+        default:
+            if (rpt_id > 7) {
+                char_handle = rpt_id;
+                APPL_TRACE_DEBUG("bta_hh_le_get_rpt: read PNP ID char handle = %d\n ",char_handle);
+                BTA_GATTC_ReadCharacteristic(p_cb->conn_id, char_handle, BTA_GATT_AUTH_REQ_NONE);
+                return;
+            }
+    }
+#endif
+    p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc[srvc_inst].report, p_cb->mode, r_type, rpt_id);
     if (p_rpt == NULL) {
         APPL_TRACE_ERROR("%s: no matching report", __func__);
         return;
     }
-
+    APPL_TRACE_DEBUG("bta_hh_le_get_rpt UUID:%d", p_rpt->uuid);
     p_cb->w4_evt = BTA_HH_GET_RPT_EVT;
     gatt_queue_read_op(GATT_READ_CHAR, p_cb->conn_id, p_rpt->char_inst_id);
 }
@@ -2346,7 +2419,7 @@
 ** Returns          void
 **
 *******************************************************************************/
-void bta_hh_le_write_rpt(tBTA_HH_DEV_CB *p_cb,
+void bta_hh_le_write_rpt(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst,
                          tBTA_HH_RPT_TYPE r_type,
                          BT_HDR *p_buf, UINT16 w4_evt )
 {
@@ -2362,9 +2435,8 @@
     /* strip report ID from the data */
     p_value = (UINT8 *)(p_buf + 1) + p_buf->offset;
     STREAM_TO_UINT8(rpt_id, p_value);
-    p_buf->len -= 1;
 
-    p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc.report, p_cb->mode, r_type, rpt_id);
+    p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc[srvc_inst].report, p_cb->mode, r_type, rpt_id);
 
     if (p_rpt == NULL) {
         APPL_TRACE_ERROR("%s: no matching report", __func__);
@@ -2372,12 +2444,17 @@
         return;
     }
 
+    p_buf->len -= 1;
+    APPL_TRACE_DEBUG("bta_hh_le_write_rpt: ReportID: 0x%02x Data Len: %d", rpt_id, p_buf->len);
     p_cb->w4_evt = w4_evt;
-
-    const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_cb->conn_id,
-                                                                          p_rpt->char_inst_id);
-
     tBTA_GATTC_WRITE_TYPE write_type = BTA_GATTC_TYPE_WRITE;
+    const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_cb->conn_id,
+                                                                        p_rpt->char_inst_id);
+#if ((defined BLE_HH_QUALIFICATION_ENABLED && BLE_HH_QUALIFICATION_ENABLED == TRUE))
+
+    gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id, p_rpt->char_inst_id,
+                        p_buf->len, p_value, write_type);
+#endif
     if (p_char && (p_char->properties & BTA_GATT_CHAR_PROP_BIT_WRITE_NR))
         write_type = BTA_GATTC_TYPE_WRITE_NO_RSP;
 
@@ -2398,7 +2475,7 @@
 {
     ctrl_type -= BTA_HH_CTRL_SUSPEND;
 
-    gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id, p_cb->hid_srvc.control_point_handle, 1,
+    gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id, p_cb->hid_srvc[0].control_point_handle, 1,
                         &ctrl_type, BTA_GATTC_TYPE_WRITE_NO_RSP);
 }
 
@@ -2413,6 +2490,8 @@
 *******************************************************************************/
 void bta_hh_le_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
 {
+    int  srvc_inst = 0;
+    APPL_TRACE_DEBUG("current service inst:%d", p_cb->cur_srvc_index);
     switch(p_data->api_sndcmd.t_type)
     {
         case HID_TRANS_SET_PROTOCOL:
@@ -2425,24 +2504,33 @@
             break;
 
         case HID_TRANS_GET_REPORT:
-            bta_hh_le_get_rpt(p_cb,
+            for (srvc_inst=0; srvc_inst < p_cb->cur_srvc_index; srvc_inst++) {
+                bta_hh_le_get_rpt(p_cb,
+                              srvc_inst,
                               p_data->api_sndcmd.param,
                               p_data->api_sndcmd.rpt_id);
+            }
             break;
 
         case HID_TRANS_SET_REPORT:
-            bta_hh_le_write_rpt(p_cb,
+            for (srvc_inst=0; srvc_inst < p_cb->cur_srvc_index; srvc_inst++) {
+                bta_hh_le_write_rpt(p_cb,
+                                srvc_inst,
                                 p_data->api_sndcmd.param,
                                 p_data->api_sndcmd.p_data,
                                 BTA_HH_SET_RPT_EVT);
+            }
             break;
 
         case HID_TRANS_DATA:  /* output report */
 
-            bta_hh_le_write_rpt(p_cb,
+            for (srvc_inst=0; srvc_inst < p_cb->cur_srvc_index; srvc_inst++) {
+                bta_hh_le_write_rpt(p_cb,
+                                srvc_inst,
                                 p_data->api_sndcmd.param,
                                 p_data->api_sndcmd.p_data,
                                 BTA_HH_DATA_EVT);
+            }
             break;
 
         case HID_TRANS_CONTROL:
@@ -2473,10 +2561,12 @@
 *******************************************************************************/
 void bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB *p_cb)
 {
-    if (p_cb->hid_srvc.in_use)
+    UINT8 i;
+
+    for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX && p_cb->hid_srvc[i].in_use; i ++)
     {
-        p_cb->dscp_info.descriptor.dl_len = p_cb->hid_srvc.descriptor.dl_len;
-        p_cb->dscp_info.descriptor.dsc_list = p_cb->hid_srvc.descriptor.dsc_list;
+        p_cb->dscp_info.descriptor.dl_len = p_cb->hid_srvc[i].descriptor.dl_len;
+        p_cb->dscp_info.descriptor.dsc_list = p_cb->hid_srvc[i].descriptor.dsc_list;
 
         (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH *)&p_cb->dscp_info);
     }
@@ -2605,7 +2695,7 @@
     UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_int);
     UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_win);
 
-    gatt_queue_write_op(GATT_WRITE_CHAR, p_dev_cb->conn_id, p_dev_cb->scan_refresh_char_handle, 2,
+    gatt_queue_write_op(GATT_WRITE_CHAR, p_dev_cb->conn_id, p_dev_cb->scan_int_char_handle, 4,
                         value, BTA_GATTC_TYPE_WRITE_NO_RSP);
 }
 
@@ -2705,7 +2795,7 @@
 ** Returns          void
 **
 *******************************************************************************/
-void bta_hh_le_hid_read_rpt_clt_cfg(BD_ADDR bd_addr, UINT8 rpt_id)
+void bta_hh_le_hid_read_rpt_clt_cfg(BD_ADDR bd_addr, UINT8 srvc_inst)
 {
     tBTA_HH_DEV_CB *p_cb = NULL;
     tBTA_HH_LE_RPT *p_rpt ;
@@ -2719,16 +2809,20 @@
     }
 
     p_cb = &bta_hh_cb.kdev[index];
+    p_rpt = &p_cb->hid_srvc[srvc_inst].report[0];
 
-    p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc.report, p_cb->mode, BTA_HH_RPTT_INPUT, rpt_id);
-
-    if (p_rpt == NULL)
-    {
-        APPL_TRACE_ERROR("bta_hh_le_write_rpt: no matching report");
-        return;
+    while(p_rpt != NULL ) {
+        if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT) {
+            if(p_rpt->uuid == GATT_UUID_HID_REPORT) {
+                  bta_hh_le_read_char_dscrpt(p_cb, p_rpt->char_inst_id,
+                                         GATT_UUID_CHAR_CLIENT_CONFIG);
+                break;
+            }
+        }
+        if (p_rpt->index == BTA_HH_LE_RPT_MAX - 1)
+            break;
+        p_rpt++;
     }
-
-    bta_hh_le_read_char_dscrpt(p_cb, p_rpt->char_inst_id, GATT_UUID_CHAR_CLIENT_CONFIG);
     return;
 }
 
diff --git a/bta/hh/bta_hh_main.c b/bta/hh/bta_hh_main.c
index a4455ef..45e7754 100644
--- a/bta/hh/bta_hh_main.c
+++ b/bta/hh/bta_hh_main.c
@@ -289,8 +289,10 @@
     if (!p_cb)
     {
         /* BTA HH enabled already? otherwise ignore the event although it's bad*/
-        if (bta_hh_cb.p_cback != NULL)
+        if (bta_hh_cb.p_cback != NULL && p_data != NULL)
         {
+            APPL_TRACE_ERROR("bta_hh_sm_execute: event = %0x, BTA_HH_API_OPEN_EVT = %x",
+                event, BTA_HH_API_OPEN_EVT);
             switch (event)
             {
             /* no control block available for new connection */
@@ -352,6 +354,13 @@
                 cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
                 break;
 
+            case BTA_HH_API_GET_DSCP_EVT:
+                cback_event = BTA_HH_CLOSE_EVT;
+
+                cback_data.dev_status.status = BTA_HH_ERR_HDL;
+                cback_data.dev_status.handle = (UINT8)p_data->hdr.layer_specific;
+                break;
+
             default:
                 /* invalid handle, call bad API event */
                 APPL_TRACE_ERROR("wrong device handle: [%d]", p_data->hdr.layer_specific);
@@ -386,7 +395,7 @@
 
         p_cb->state = state_table[event][BTA_HH_NEXT_STATE] ;
 
-        if ((action = state_table[event][BTA_HH_ACTION]) != BTA_HH_IGNORE)
+        if ((action = state_table[event][BTA_HH_ACTION]) < BTA_HH_IGNORE)
         {
             (*bta_hh_action[action])(p_cb, p_data);
         }
@@ -456,7 +465,7 @@
                       * So if REMOVE_DEVICE is called and in_use is FALSE then we should treat this as a NULL p_cb. Hence we
                       * force the index to be IDX_INVALID
                       */
-                    if ((index != BTA_HH_IDX_INVALID) &&
+                    if ((index != BTA_HH_IDX_INVALID) && (index < BTA_HH_MAX_DEVICE) &&
                         (bta_hh_cb.kdev[index].in_use == FALSE)) {
                         index = BTA_HH_IDX_INVALID;
                     }
@@ -469,7 +478,13 @@
             else
                 index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
 
-            if (index != BTA_HH_IDX_INVALID)
+            if (p_msg->event == BTA_HH_INT_CLOSE_EVT && index == BTA_HH_IDX_INVALID)
+            {
+                /* Special handling for vc unplug event before device is opened */
+                index = bta_hh_find_cb(((tBTA_HH_CBACK_DATA *)p_msg)->addr);
+            }
+
+            if ((index != BTA_HH_IDX_INVALID)  && (index < BTA_HH_MAX_DEVICE))
                 p_cb = &bta_hh_cb.kdev[index];
 
 #if BTA_HH_DEBUG
diff --git a/bta/hh/bta_hh_utils.c b/bta/hh/bta_hh_utils.c
index c8ea864..695ddad 100644
--- a/bta/hh/bta_hh_utils.c
+++ b/bta/hh/bta_hh_utils.c
@@ -22,6 +22,8 @@
 
 
 #include "bta_hh_int.h"
+#include "device/include/interop.h"
+#include "device/include/interop_config.h"
 
 /* if SSR max latency is not defined by remote device, set the default value
    as half of the link supervision timeout */
@@ -51,6 +53,27 @@
 
 
 /*******************************************************************************
+**      Function       blacklist_adjust_sniff_subrate
+**
+**      Description    It's used to update SSR parameter such as max latency,
+**                     if device is found in HID blacklist.
+**
+**      Returns        None
+*******************************************************************************/
+static void blacklist_adjust_sniff_subrate(BD_ADDR peer_dev, UINT16 *ssr_max_lat)
+{
+    UINT16 old_ssr_max_lat = *ssr_max_lat;
+    bt_bdaddr_t remote_bdaddr;
+    bdcpy(remote_bdaddr.address, peer_dev);
+    if (interop_match_addr_get_max_lat(INTEROP_UPDATE_HID_SSR_MAX_LAT, &remote_bdaddr,
+        ssr_max_lat)) {
+        APPL_TRACE_WARNING("%s: Device in blacklist for ssr, max latency changed "
+            "from %d to %d", __func__, old_ssr_max_lat, *ssr_max_lat);
+    }
+}
+
+
+/*******************************************************************************
 **
 ** Function         bta_hh_find_cb
 **
@@ -187,7 +210,8 @@
                                UINT8 app_id)
 {
 #if BTA_HH_DEBUG
-    APPL_TRACE_DEBUG("subclass = 0x%2x", sub_class);
+    APPL_TRACE_DEBUG("subclass = 0x%2x, maxlat = 0x%2x, minto = 0x%2x",
+                     sub_class, ssr_max_latency, ssr_min_tout);
 #endif
 
     p_cb->hid_handle = handle;
@@ -198,6 +222,8 @@
     p_cb->app_id    = app_id;
 
     p_cb->dscp_info.ssr_max_latency = ssr_max_latency;
+    blacklist_adjust_sniff_subrate(p_cb->addr, &(p_cb->dscp_info.ssr_max_latency));
+
     p_cb->dscp_info.ssr_min_tout    = ssr_min_tout;
 
     /* store report descriptor info */
@@ -240,7 +266,7 @@
         }
     }
 #if BTA_HH_DEBUG
-            APPL_TRACE_EVENT("bta_hh_tod_spt sub_class:0x%x NOT supported", sub_class);
+    APPL_TRACE_ERROR("bta_hh_tod_spt sub_class:0x%x NOT supported", sub_class);
 #endif
     return FALSE;
 }
@@ -423,11 +449,15 @@
 
                 BTM_GetLinkSuperTout(p_cb->kdev[i].addr, &ssr_max_latency) ;
                 ssr_max_latency = BTA_HH_GET_DEF_SSR_MAX_LAT(ssr_max_latency);
+                APPL_TRACE_DEBUG("ssr_max_latency: 0x%2x", ssr_max_latency);
 
                 /* per 1.1 spec, if the newly calculated max latency is greater than
                 BTA_HH_SSR_MAX_LATENCY_DEF which is 500ms, use BTA_HH_SSR_MAX_LATENCY_DEF */
-                if (ssr_max_latency > BTA_HH_SSR_MAX_LATENCY_DEF)
+                if (ssr_max_latency > BTA_HH_SSR_MAX_LATENCY_DEF) {
                     ssr_max_latency = BTA_HH_SSR_MAX_LATENCY_DEF;
+                    APPL_TRACE_DEBUG("Updating ssr_max_latency to: 0x%2x",
+                        BTA_HH_SSR_MAX_LATENCY_DEF);
+                }
 
                 * p_max_ssr_lat  = ssr_max_latency;
             }
@@ -439,6 +469,8 @@
             else
                 * p_min_ssr_tout = p_cb->kdev[i].dscp_info.ssr_min_tout;
 
+            APPL_TRACE_DEBUG("max_lat: 0x%2x, min to: 0x%2x", * p_max_ssr_lat,
+                                * p_min_ssr_tout);
             status           = BTA_HH_OK;
 
             break;
@@ -465,7 +497,12 @@
     for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++) {
         osi_free_and_reset((void **)&bta_hh_cb.kdev[xx].dscp_info.descriptor.dsc_list);
     }
-    osi_free_and_reset((void **)&bta_hh_cb.p_disc_db);
+
+    if (bta_hh_cb.p_disc_db) {
+        /* Cancel SDP if it had been started. */
+        (void)SDP_CancelServiceSearch (bta_hh_cb.p_disc_db);
+        osi_free_and_reset((void **)&bta_hh_cb.p_disc_db);
+    }
 
     (* bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, (tBTA_HH *)&status);
     /* all connections are down, no waiting for diconnect */
diff --git a/bta/hl/bta_hl_act.c b/bta/hl/bta_hl_act.c
index fe7fc2c..bb15cf4 100644
--- a/bta/hl/bta_hl_act.c
+++ b/bta/hl/bta_hl_act.c
@@ -414,7 +414,7 @@
     tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
     tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
     tMCA_RESULT         result;
-    tBTA_HL_STATUS      status = BTA_HL_STATUS_OK;
+    tBTA_HL_STATUS      status;
     BOOLEAN             free_buf = FALSE;
     BOOLEAN             close_dch = FALSE;
     tBTA_HL             evt_data;
@@ -423,7 +423,11 @@
 #if (BTA_HL_DEBUG == TRUE)
     APPL_TRACE_DEBUG("bta_hl_dch_ci_get_tx_data");
 #endif
-
+    if (p_data != NULL)
+    {
+        status = p_data->ci_get_put_data.status;
+        APPL_TRACE_WARNING("bta_hl_dch_ci_put_rx_data:status=%d", status);
+    }
     p_dcb->cout_oper &= ~BTA_HL_CO_GET_TX_DATA_MASK;
 
     if (p_dcb->close_pending)
@@ -436,6 +440,10 @@
             close_dch = TRUE;
         }
     }
+    else if (status == BTA_HL_STATUS_FAIL)
+    {
+        free_buf = TRUE;
+    }
     else
     {
         if ((result = MCA_WriteReq((tMCA_DL) p_dcb->mdl_handle, p_dcb->p_tx_pkt)) != MCA_SUCCESS)
diff --git a/bta/hl/bta_hl_main.c b/bta/hl/bta_hl_main.c
index 8bf2bc6..6a2e499 100644
--- a/bta/hl/bta_hl_main.c
+++ b/bta/hl/bta_hl_main.c
@@ -440,7 +440,7 @@
 
     for (i = 0; i < BTA_HL_CCH_ACTIONS; i++)
     {
-        if ((action = state_table[event][i]) != BTA_HL_CCH_IGNORE)
+        if ((action = state_table[event][i]) < BTA_HL_CCH_IGNORE)
         {
             (*bta_hl_cch_action[action])(app_idx, mcl_idx, p_data);
         }
@@ -497,7 +497,7 @@
 
     for (i = 0; i < BTA_HL_DCH_ACTIONS; i++)
     {
-        if ((action = state_table[event][i]) != BTA_HL_DCH_IGNORE)
+        if ((action = state_table[event][i]) < BTA_HL_DCH_IGNORE)
         {
             (*bta_hl_dch_action[action])(app_idx, mcl_idx, mdl_idx, p_data);
         }
diff --git a/bta/include/bta_ag_api.h b/bta/include/bta_ag_api.h
index e281fb1..64a6e0b 100644
--- a/bta/include/bta_ag_api.h
+++ b/bta/include/bta_ag_api.h
@@ -30,20 +30,6 @@
 /*****************************************************************************
 **  Constants and data types
 *****************************************************************************/
-#define HFP_VERSION_1_1         0x0101
-#define HFP_VERSION_1_5         0x0105
-#define HFP_VERSION_1_6         0x0106
-#define HFP_VERSION_1_7         0x0107
-
-#define HSP_VERSION_1_0         0x0100
-#define HSP_VERSION_1_2         0x0102
-
-/* Note, if you change the default version here, please also change the one in
- * bta_hs_api.h, they are meant to be the same.
- */
-#ifndef BTA_HFP_VERSION
-#define BTA_HFP_VERSION         HFP_VERSION_1_7
-#endif
 
 /* AG feature masks */
 #define BTA_AG_FEAT_3WAY    0x00000001   /* Three-way calling */
@@ -56,20 +42,15 @@
 #define BTA_AG_FEAT_ECC     0x00000080   /* Enhanced Call Control */
 #define BTA_AG_FEAT_EXTERR  0x00000100   /* Extended error codes */
 #define BTA_AG_FEAT_CODEC   0x00000200   /* Codec Negotiation */
-
-#define HFP_1_6_FEAT_MASK   0x000003FF   /* Valid feature bit mask for HFP 1.6 (and below) */
-
-/* HFP 1.7+ */
-#define BTA_AG_FEAT_HF_IND  0x00000400   /* HF Indicators */
-#define BTA_AG_FEAT_ESCO    0x00000800   /* eSCO S4 (and T2) setting supported */
-
+#define BTA_AG_FEAT_HFIND   0x00000400   /* HF indicators */
+#define BTA_AG_FEAT_S4      0x00000800   /* ESCO S4 link setting */
+#define BTA_AG_FEAT_VOIP    0x00001000   /* VoIP call */
 
 /* Proprietary features: using 31 ~ 16 bits */
 #define BTA_AG_FEAT_BTRH    0x00010000   /* CCAP incoming call hold */
 #define BTA_AG_FEAT_UNAT    0x00020000   /* Pass unknown AT commands to application */
 #define BTA_AG_FEAT_NOSCO   0x00040000   /* No SCO control performed by BTA AG */
 #define BTA_AG_FEAT_NO_ESCO 0x00080000   /* Do not allow or use eSCO */
-#define BTA_AG_FEAT_VOIP    0x00100000   /* VoIP call */
 
 typedef UINT32 tBTA_AG_FEAT;
 
@@ -85,9 +66,6 @@
 #define BTA_AG_FAIL_RFCOMM      2 /* Open failed due to RFCOMM */
 #define BTA_AG_FAIL_RESOURCES   3 /* out of resources failure  */
 
-/*Status to disallow passing AT Events after BTIF */
-
-#define BTA_AG_DISALLOW_AT      5
 typedef UINT8 tBTA_AG_STATUS;
 
 /* handle values used with BTA_AgResult */
@@ -99,17 +77,6 @@
  * They donot interfere with each other
  */
 
-/* Number of supported HF indicators, there is one HF indicator so far i.e.
-                                                   enhanced driver status. */
-/* Number of supported HF indicators,
-   1 for Enhanced Safety Status
-   2 for Battery Level Status */
-#ifndef BTA_AG_NUM_LOCAL_HF_IND
-#define BTA_AG_NUM_LOCAL_HF_IND     2
-#endif
-
-
-
 #define BTA_AG_HANDLE_SCO_NO_CHANGE 0xFFFF
 
 /* AG result codes used with BTA_AgResult */
@@ -135,7 +102,8 @@
 #define BTA_AG_IN_CALL_HELD_RES     19  /* Incoming call held */
 #define BTA_AG_UNAT_RES             20  /* Response to unknown AT command event */
 #define BTA_AG_MULTI_CALL_RES       21  /* SLC at three way call */
-#define BTA_AG_BIND_RES             22  /* Activate/Deactivate HF indicator */
+#define BTA_AG_BIND_RES             22  /* Send indicator response for AT+BIND */
+
 
 typedef UINT8 tBTA_AG_RES;
 
@@ -148,14 +116,11 @@
 #define BTA_AG_PEER_FEAT_ECS        0x0020  /* Enhanced Call Status */
 #define BTA_AG_PEER_FEAT_ECC        0x0040  /* Enhanced Call Control */
 #define BTA_AG_PEER_FEAT_CODEC      0x0080  /* Codec Negotiation */
-#define BTA_AG_PEER_FEAT_HF_IND     0x0100   /* HF Indicators */
-#define BTA_AG_PEER_FEAT_ESCO       0x0200   /* eSCO S4 (and T2) setting supported */
+#define BTA_AG_PEER_FEAT_HFIND      0x0100  /* HF indicators */
+#define BTA_AG_PEER_FEAT_S4         0x0200  /* ESCO S4 link settings */
+#define BTA_AG_PEER_FEAT_VOIP       0x0400  /* VoIP call */
 
-/* Proprietary features: using bits after 12 */
-#define BTA_AG_PEER_FEAT_UNAT       0x1000   /* Pass unknown AT command responses to application */
-#define BTA_AG_PEER_FEAT_VOIP       0x2000  /* VoIP call */
-
-typedef uint16_t tBTA_AG_PEER_FEAT;
+typedef UINT16 tBTA_AG_PEER_FEAT;
 
 /* HFP peer supported codec masks */
 // TODO(google) This should use common definitions
@@ -165,6 +130,10 @@
 #define BTA_AG_CODEC_MSBC           BTM_SCO_CODEC_MSBC      /* mSBC */
 typedef UINT16 tBTA_AG_PEER_CODEC;
 
+/* HFP peer supported HF indicator assigned numbers */
+#define BTM_AG_HFIND_NONE                      0
+#define BTA_AG_HFIND_ENHANCED_SAFETY           1      /* Enhanced Safety HF indicator */
+
 /* HFP errcode - Set when BTA_AG_OK_ERROR is returned in 'ok_flag' */
 #define BTA_AG_ERR_PHONE_FAILURE    0       /* Phone Failure */
 #define BTA_AG_ERR_NO_CONN_PHONE    1       /* No connection to phone */
@@ -244,12 +213,18 @@
 #define BTA_AG_AT_MAX_LEN           256
 #endif
 
+/* AT command argument capabilities */
+#define BTA_AG_AT_NONE          0x01        /* no argument */
+#define BTA_AG_AT_SET           0x02        /* set value */
+#define BTA_AG_AT_READ          0x04        /* read value */
+#define BTA_AG_AT_TEST          0x08        /* test value range */
+#define BTA_AG_AT_FREE          0x10        /* freeform argument */
+
 /* data associated with BTA_AG_IND_RES */
 typedef struct
 {
-    uint16_t          id;
-    uint16_t          value;
-    bool              on_demand;
+    UINT16          id;
+    UINT16          value;
 } tBTA_AG_IND;
 
 /* data type for BTA_AgResult() */
@@ -298,8 +273,10 @@
 #define BTA_AG_AT_CBC_EVT       25 /* Battery Level report from HF */
 #define BTA_AG_AT_BAC_EVT       26 /* avablable codec */
 #define BTA_AG_AT_BCS_EVT       27 /* Codec select */
-#define BTA_AG_AT_BIND_EVT      28 /* HF indicator */
-#define BTA_AG_AT_BIEV_EVT      29 /* HF indicator updates from peer */
+#define BTA_AG_AT_BIND_EVT      28 /* Read HF indicators supported values */
+#define BTA_AG_AT_BIEV_EVT      29 /* HF indicator value update from HF*/
+
+
 
 typedef UINT8 tBTA_AG_EVT;
 
@@ -351,7 +328,6 @@
     char                str[BTA_AG_AT_MAX_LEN+1];
     UINT16              num;
     UINT8               idx;    /* call number used by CLCC and CHLD */
-    UINT16              lidx;    /* long index, ex, HF indicator */
 } tBTA_AG_VAL;
 
 /* union of data associated with AG callback */
@@ -415,24 +391,13 @@
 #define BTA_AG_BEARER_RES2          6   /* Reserved     */
 #define BTA_AG_BEARER_RES3          7   /* Reserved     */
 
-/* type for HF indicator */
-typedef struct
-{
-    UINT16          ind_id;
-    BOOLEAN         is_supported;
-    BOOLEAN         is_enable;
-    UINT32          ind_min_val;
-    UINT32          ind_max_val;
-} tBTA_AG_HF_IND;
 
 /* AG configuration structure */
 typedef struct
 {
     char         *cind_info;
-    char         *bind_info;
-    uint8_t        num_local_hf_ind;
-    int32_t        conn_tout;
-    uint16_t       sco_pkt_types;
+    INT32        conn_tout;
+    UINT16       sco_pkt_types;
     char         *chld_val_ecc;
     char         *chld_val;
 } tBTA_AG_CFG;
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index 4a8cd5f..0984f2c 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -392,12 +392,22 @@
 /* advertising instance parameters */
 typedef struct
 {
-    UINT16                  adv_int_min;            /* minimum adv interval */
-    UINT16                  adv_int_max;            /* maximum adv interval */
-    tBTA_BLE_ADV_EVT        adv_type;               /* adv event type */
+    UINT32                  adv_int_min;            /* minimum adv interval */
+    UINT32                  adv_int_max;            /* maximum adv interval */
+    UINT16                  adv_type;               /* adv event type */
     tBTA_BLE_ADV_CHNL_MAP   channel_map;            /* adv channel map */
     tBTA_BLE_AFP            adv_filter_policy;      /* advertising filter policy */
     tBTA_BLE_ADV_TX_POWER   tx_power;               /* adv tx power */
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    UINT8                   pri_phy;
+    UINT8                   sec_adv_max_skip;       /* max adv events skipped before AUX_ADV_IND is sent */
+    UINT8                   sec_adv_phy;            /* PHY for secondary channel */
+    UINT8                   adv_sid;
+    UINT8                   scan_req_notf_enb;      /* send scan req notifications from controller */
+    UINT16                  duration;               /* duration of adv */
+    UINT8                   max_ext_adv_evts;
+    UINT8                   frag_pref;
+#endif
 }tBTA_BLE_ADV_PARAMS;
 
 /* These are the fields returned in each device adv packet.  It
@@ -593,7 +603,8 @@
 #define BTA_DM_HW_ERROR_EVT             26      /* BT Chip H/W error */
 #define BTA_DM_LE_FEATURES_READ         27      /* Cotroller specific LE features are read */
 #define BTA_DM_ENER_INFO_READ           28      /* Energy info read */
-#define BTA_DM_BLE_SC_OOB_REQ_EVT       29      /* SMP SC OOB request event */
+#define BTA_DM_LE_ADV_EXT_FEATURES_READ 29
+#define BTA_DM_BLE_SC_OOB_REQ_EVT       30      /* SMP SC OOB request event */
 typedef uint8_t tBTA_DM_SEC_EVT;
 
 /* Structure associated with BTA_DM_ENABLE_EVT */
@@ -726,6 +737,7 @@
     UINT8           fail_reason;        /* The HCI reason/error code for when success=FALSE */
     tBLE_ADDR_TYPE  addr_type;          /* Peer device address type */
     tBT_DEVICE_TYPE dev_type;
+    BOOLEAN         smp_over_br;        /* SMP pairing done over BR/EDR link CID 7 */
 } tBTA_DM_AUTH_CMPL;
 
 
@@ -905,6 +917,10 @@
 #define BTA_BLE_MULTI_ADV_DISABLE_EVT       2
 #define BTA_BLE_MULTI_ADV_PARAM_EVT         3
 #define BTA_BLE_MULTI_ADV_DATA_EVT          4
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+#define BTA_BLE_EXTENDED_ADV_ENB_EVT        5
+#define BTA_BLE_EXTENDED_ADV_PARAM_EVT      6
+#endif
 
 typedef UINT8 tBTA_BLE_MULTI_ADV_EVT;
 
@@ -972,6 +988,12 @@
     tBTA_DM_BLE_PF_ADV_TRACK_ENTRIES num_of_tracking_entries;
 } tBTA_DM_BLE_PF_FILT_PARAMS;
 
+/* HCI RAW Command Callback */
+typedef tBTM_RAW_CMPL_CB        tBTA_RAW_CMPL_CBACK;
+
+/* Vendor Specific Command Callback */
+typedef tBTM_VSC_CMPL_CB        tBTA_VENDOR_CMPL_CBACK;
+
 /* Search callback events */
 #define BTA_DM_INQ_RES_EVT              0       /* Inquiry result for a peer device. */
 #define BTA_DM_INQ_CMPL_EVT             1       /* Inquiry complete. */
@@ -995,6 +1017,7 @@
     BOOLEAN         is_limited;             /* TRUE, if the limited inquiry bit is set in the CoD */
     INT8            rssi;                   /* The rssi value */
     UINT8           *p_eir;                 /* received EIR */
+    UINT16          adv_data_len;
 #if (BLE_INCLUDED == TRUE)
     UINT8               inq_result_type;
     UINT8               ble_addr_type;
@@ -1226,8 +1249,8 @@
 #endif
 
 #ifndef BTA_DM_PM_SNIFF2_MAX
-#define BTA_DM_PM_SNIFF2_MAX     180
-#define BTA_DM_PM_SNIFF2_MIN     150
+#define BTA_DM_PM_SNIFF2_MAX     54
+#define BTA_DM_PM_SNIFF2_MIN     30
 #define BTA_DM_PM_SNIFF2_ATTEMPT 4
 #define BTA_DM_PM_SNIFF2_TIMEOUT 1
 #endif
@@ -1253,6 +1276,13 @@
 #define BTA_DM_PM_SNIFF5_TIMEOUT 0
 #endif
 
+#ifndef BTA_DM_PM_SNIFF6_MAX
+#define BTA_DM_PM_SNIFF6_MAX     30
+#define BTA_DM_PM_SNIFF6_MIN     10
+#define BTA_DM_PM_SNIFF6_ATTEMPT 4
+#define BTA_DM_PM_SNIFF6_TIMEOUT 1
+#endif
+
 #ifndef BTA_DM_PM_PARK_MAX
 #define BTA_DM_PM_PARK_MAX       800
 #define BTA_DM_PM_PARK_MIN       400
@@ -1402,6 +1432,34 @@
 
 /*******************************************************************************
 **
+** Function         BTA_DmHciRawCommand
+**
+** Description      This function sends the HCI RAW command
+**                  to the controller
+**
+**
+** Returns          tBTA_STATUS
+**
+*******************************************************************************/
+extern tBTA_STATUS BTA_DmHciRawCommand (UINT16 opcode, UINT8 param_len,UINT8 *p_param_buf, tBTA_RAW_CMPL_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_DmVendorSpecificCommand
+**
+** Description      This function sends the vendor specific command
+**                  to the controller
+**
+**
+** Returns          tBTA_STATUS
+**
+*******************************************************************************/
+extern tBTA_STATUS BTA_DmVendorSpecificCommand (UINT16 opcode,
+            UINT8 param_len,UINT8 *p_param_buf, tBTA_VENDOR_CMPL_CBACK *p_cback);
+
+
+/*******************************************************************************
+**
 ** Function         BTA_DmSearch
 **
 ** Description      This function searches for peer Bluetooth devices.  It
@@ -1844,8 +1902,9 @@
 ** Returns          void
 **
 *******************************************************************************/
-extern void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval,
-                                   UINT32 scan_window, tBLE_SCAN_MODE scan_mode,
+extern void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT8 scan_phys, UINT32 scan_interval,
+                                   UINT32 scan_window, UINT16 scan_interval_coded,
+                                   UINT16 scan_window_coded, tBLE_SCAN_MODE scan_mode,
                                    tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_status_cback);
 
 /*******************************************************************************
@@ -1967,7 +2026,7 @@
 ** Returns          void
 **
 *******************************************************************************/
-extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
+extern void BTA_DmBleObserve(BOOLEAN start, UINT16 duration, UINT16 period,
                              tBTA_DM_SEARCH_CBACK *p_results_cb);
 
 
@@ -2090,7 +2149,7 @@
 **
 *******************************************************************************/
 extern void BTA_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
-                                tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_data);
+                                tBTA_BLE_AD_MASK data_mask, UINT8 frag_pref, tBTA_BLE_ADV_DATA *p_data);
 
 /*******************************************************************************
 **
@@ -2136,6 +2195,30 @@
 
 /*******************************************************************************
 **
+** Function         BTA_DmBleSetPhy
+**
+** Description      This function is to set Tx and Rx Phy for a connection
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBleSetPhy(BD_ADDR remote_device, UINT8 all_phy,
+                            UINT8 tx_phy, UINT8 rx_phy, UINT16 phy_options);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetDefaultPhy
+**
+** Description      This function is to set default Tx and Rx Phy
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBleSetDefaultPhy(UINT8 all_phy,
+                            UINT8 tx_phy, UINT8 rx_phy);
+
+/*******************************************************************************
+**
 ** Function         BTA_DmBleSetStorageParams
 **
 ** Description      This function is called to set the storage parameters
diff --git a/bta/include/bta_av_aac.h b/bta/include/bta_av_aac.h
new file mode 100644
index 0000000..310cbfa
--- /dev/null
+++ b/bta/include/bta_av_aac.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *   met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of The Linux Foundation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+  ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  Interface to utility functions for AAC codec
+ *
+ ******************************************************************************/
+#ifndef BTA_AV_AAC_H
+#define BTA_AV_AAC_H
+
+
+/* AAC packet header size */
+#define BTA_AV_AAC_HDR_SIZE         A2D_AAC_MPL_HDR_LEN
+
+/*******************************************************************************
+**
+** Function         bta_av_aac_cfg_in_cap
+**
+** Description      Checks if AAC codec config is allowed for given caps.
+**                  codec config bits are also checked for sanity
+**
+** Returns          0 if ok, nonzero if error.
+**
+*******************************************************************************/
+extern UINT8 bta_av_aac_cfg_in_cap(UINT8 *p_cfg, tA2D_AAC_CIE *p_cap);
+
+#endif /* BTA_AV_AAC_H */
+
diff --git a/bta/include/bta_av_api.h b/bta/include/bta_av_api.h
index 701d90c..7dd1e6f 100644
--- a/bta/include/bta_av_api.h
+++ b/bta/include/bta_av_api.h
@@ -1,4 +1,10 @@
 /******************************************************************************
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a contribution.
+ ******************************************************************************/
+
+/******************************************************************************
  *
  *  Copyright (C) 2004-2012 Broadcom Corporation
  *
@@ -60,6 +66,7 @@
 #define BTA_AV_FEAT_METADATA    0x0040  /* remote control Metadata Transfer command/response */
 #define BTA_AV_FEAT_MULTI_AV    0x0080  /* use multi-av, if controller supports it */
 #define BTA_AV_FEAT_BROWSE      0x0010  /* use browsing channel */
+#define BTA_AV_FEAT_CA          0x0020  /* use cover art */
 #define BTA_AV_FEAT_MASTER      0x0100  /* stream only as master role */
 #define BTA_AV_FEAT_ADV_CTRL    0x0200  /* remote control Advanced Control command/response */
 #define BTA_AV_FEAT_DELAY_RPT   0x0400  /* allow delay reporting */
@@ -67,6 +74,7 @@
 #define BTA_AV_FEAT_APP_SETTING 0x2000  /* Player app setting support */
 
 /* Internal features */
+#define BTA_AV_FEAT_AVRC_UI_UPDATE 0x4000 /* Update UI to show notification for browsing capable remote*/
 #define BTA_AV_FEAT_NO_SCO_SSPD 0x8000  /* Do not suspend av streaming as to AG events(SCO or Call) */
 
 typedef UINT16 tBTA_AV_FEAT;
@@ -89,15 +97,17 @@
 /* offset of codec type in codec info byte array */
 #define BTA_AV_CODEC_TYPE_IDX       AVDT_CODEC_TYPE_INDEX   /* 2 */
 
-
-
 /* maximum number of streams created: 1 for audio, 1 for video */
 #ifndef BTA_AV_NUM_STRS
 #define BTA_AV_NUM_STRS         2
 #endif
 
 #ifndef BTA_AV_MAX_SEPS
-#define BTA_AV_MAX_SEPS         2
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+#define BTA_AV_MAX_SEPS         4
+#else
+#define BTA_AV_MAX_SEPS         3
+#endif
 #endif
 
 #ifndef BTA_AV_MAX_A2DP_MTU
@@ -126,6 +136,9 @@
 /* Company ID in BT assigned numbers */
 #define BTA_AV_BT_VENDOR_ID     VDP_BT_VENDOR_ID        /* Broadcom Corporation */
 
+/* Offset for codec configuration in codec info */
+#define BTA_AV_CFG_START_IDX    3
+
 /* vendor specific codec ID */
 #define BTA_AV_CODEC_ID_H264    VDP_CODEC_ID_H264       /* Non-VDP codec ID - H.264 */
 #define BTA_AV_CODEC_ID_IMG     VDP_CODEC_ID_IMG        /* Non-VDP codec ID - images/slideshow */
@@ -254,9 +267,12 @@
 #define BTA_AV_MEDIA_SINK_CFG_EVT    20 /* command to configure codec */
 #define BTA_AV_MEDIA_DATA_EVT   21      /* sending data to Media Task */
 #define BTA_AV_OFFLOAD_START_RSP_EVT 22 /* a2dp offload start response */
-/* Max BTA event */
-#define BTA_AV_MAX_EVT          23
+#define BTA_AV_BROWSE_MSG_EVT   23      /* Browse MSG EVT */
+#define BTA_AV_ROLE_CHANGED_EVT     24
+#define BTA_AV_RC_COLL_DETECTED_EVT     25       /* RC channel collosion detected */
 
+/* Max BTA event */
+#define BTA_AV_MAX_EVT          26
 
 typedef UINT8 tBTA_AV_EVT;
 
@@ -289,6 +305,10 @@
     BOOLEAN         starting;
     tBTA_AV_EDR     edr;        /* 0, if peer device does not support EDR */
     UINT8           sep;        /*  sep type of peer device */
+    UINT8           role;       /* 0x00 master, 0x01 slave , 0xFF unkown*/
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+    UINT16          stream_chnl_id;
+#endif
 } tBTA_AV_OPEN;
 
 /* data associated with BTA_AV_CLOSE_EVT */
@@ -306,6 +326,7 @@
     tBTA_AV_STATUS  status;
     BOOLEAN         initiator; /* TRUE, if local device initiates the START */
     BOOLEAN         suspending;
+    UINT8           role;       /* 0x00 master, 0x01 slave , 0xFF unkown*/
 } tBTA_AV_START;
 
 /* data associated with BTA_AV_SUSPEND_EVT */
@@ -360,6 +381,13 @@
     BD_ADDR         peer_addr;
 } tBTA_AV_RC_CLOSE;
 
+/* data associated with BTA_AV_RC_COLL_DETECTED */
+typedef struct
+{
+    UINT8           rc_handle;
+    BD_ADDR         peer_addr;
+} tBTA_AV_RC_COLL_DETECTED;
+
 /* data associated with BTA_AV_RC_FEAT_EVT */
 typedef struct
 {
@@ -415,10 +443,19 @@
     tAVRC_MSG       *p_msg;
 } tBTA_AV_META_MSG;
 
+/*data associated with BTA_AV_BROWSE_MSG_EVT */
+typedef struct
+{
+    UINT8           rc_handle;
+    UINT8           label;
+    tAVRC_MSG       *p_msg;
+}tBTA_AV_BROWSE_MSG;
+
 /* data associated with BTA_AV_PENDING_EVT */
 typedef struct
 {
     BD_ADDR         bd_addr;
+    tBTA_AV_HNDL    hndl;    /* Handle associated with the stream. */
 } tBTA_AV_PEND;
 
 /* data associated with BTA_AV_REJECT_EVT */
@@ -428,6 +465,13 @@
     tBTA_AV_HNDL    hndl;       /* Handle associated with the stream that rejected the connection. */
 } tBTA_AV_REJECT;
 
+/* data associated with BTA_AV_ROLE_CHANGED */
+typedef struct
+{
+    BD_ADDR  bd_addr;
+    UINT8    new_role;
+    tBTA_AV_HNDL    hndl;       /* Handle associated with role change event */
+} tBTA_AV_ROLE_CHANGED;
 
 /* union of data associated with AV callback */
 typedef union
@@ -442,6 +486,7 @@
     tBTA_AV_PROTECT_RSP protect_rsp;
     tBTA_AV_RC_OPEN     rc_open;
     tBTA_AV_RC_CLOSE    rc_close;
+    tBTA_AV_RC_COLL_DETECTED rc_col_detected;
     tBTA_AV_REMOTE_CMD  remote_cmd;
     tBTA_AV_REMOTE_RSP  remote_rsp;
     tBTA_AV_VENDOR      vendor_cmd;
@@ -450,9 +495,11 @@
     tBTA_AV_SUSPEND     suspend;
     tBTA_AV_PEND        pend;
     tBTA_AV_META_MSG    meta_msg;
+    tBTA_AV_BROWSE_MSG  browse_msg;
     tBTA_AV_REJECT      reject;
     tBTA_AV_RC_FEAT     rc_feat;
     tBTA_AV_STATUS      status;
+    tBTA_AV_ROLE_CHANGED role_changed;
 } tBTA_AV;
 
 typedef struct
@@ -635,25 +682,47 @@
 **
 ** Function         BTA_AvStart
 **
-** Description      Start audio/video stream data transfer.
+** Description      Start audio/video stream data transfer on the AV handle.
 **
 ** Returns          void
 **
 *******************************************************************************/
-void BTA_AvStart(void);
+void BTA_AvStart(tBTA_AV_HNDL hndl);
 
 /*******************************************************************************
 **
 ** Function         BTA_AvStop
 **
-** Description      Stop audio/video stream data transfer.
+** Description      Stop audio/video stream data transfer on the AV handle.
 **                  If suspend is TRUE, this function sends AVDT suspend signal
 **                  to the connected peer(s).
 **
 ** Returns          void
 **
 *******************************************************************************/
-void BTA_AvStop(BOOLEAN suspend);
+void BTA_AvStop(BOOLEAN suspend, tBTA_AV_HNDL handle);
+
+/*******************************************************************************
+**
+** Function         BTA_AvEnableMultiCast
+**
+** Description      Enable/disable Avdtp MultiCast
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvEnableMultiCast(BOOLEAN state, tBTA_AV_HNDL handle);
+
+/*******************************************************************************
+**
+** Function         BTA_AvUpdateMaxAVClient
+**
+** Description      Update max simultaneous AV connections supported
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvUpdateMaxAVClient(UINT8 max_clients);
 
 /*******************************************************************************
 **
@@ -834,6 +903,16 @@
 *******************************************************************************/
 void BTA_AvOffloadStartRsp(tBTA_AV_HNDL hndl, tBTA_AV_STATUS status);
 
+/*******************************************************************************
+**
+** Function         bta_av_get_codec_type
+**
+** Description      Returns the codec_type from the most recently used scb
+**
+** Returns          Codec type corresponding to AV handle
+**
+*******************************************************************************/
+UINT8 bta_av_get_codec_type(tBTA_AV_HNDL hndl);
 
 #ifdef __cplusplus
 }
diff --git a/bta/include/bta_av_co.h b/bta/include/bta_av_co.h
index ad8e697..661cb7b 100644
--- a/bta/include/bta_av_co.h
+++ b/bta/include/bta_av_co.h
@@ -59,6 +59,23 @@
     BTA_AV_CO_ST_STREAM
 };
 
+enum
+{
+    BTIF_SV_AV_AA_SBC_INDEX = 0,
+    BTIF_SV_AV_AA_APTX_INDEX,
+    BTIF_SV_AV_AA_APTX_HD_INDEX,
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    BTIF_SV_AV_AA_AAC_INDEX,
+#endif
+    BTIF_SV_AV_AA_SRC_SEP_INDEX  /* Last index */
+};
+
+enum
+{
+    BTIF_SV_AV_AA_SBC_SINK_INDEX = BTIF_SV_AV_AA_SRC_SEP_INDEX,
+    BTIF_SV_AV_AA_SNK_SEP_INDEX  /* Last index */
+};
+
 
 /* data type for the Audio Codec Information*/
 typedef struct
@@ -388,4 +405,28 @@
 *******************************************************************************/
 extern void bta_av_co_video_delay(tBTA_AV_HNDL hndl, UINT16 delay);
 
+/*******************************************************************************
+**
+** Function         bta_av_co_audio_is_offload_supported
+**
+** Description      This function is called by AV to check if DUT is in offload
+**                  mode.
+**
+** Returns          TRUE if offload is enabled, FALSE otherwise
+**
+*******************************************************************************/
+extern BOOLEAN bta_av_co_audio_is_offload_supported(void);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_audio_is_codec_supported
+**
+** Description      This function is called by AV to check if corresponding
+**                  codec is supported in offload mode.
+**
+** Returns          TRUE if codec is supported in offload, FALSE otherwise
+**
+*******************************************************************************/
+extern BOOLEAN bta_av_co_audio_is_codec_supported(int codec);
+
 #endif /* BTA_AV_CO_H */
diff --git a/bta/include/bta_gatt_api.h b/bta/include/bta_gatt_api.h
index 4c9f76c..b55dfc7 100644
--- a/bta/include/bta_gatt_api.h
+++ b/bta/include/bta_gatt_api.h
@@ -146,6 +146,10 @@
 #define BTA_GATTC_SCAN_FLT_PARAM_EVT 32 /* Param filter event */
 #define BTA_GATTC_SCAN_FLT_STATUS_EVT 33 /* Filter status event */
 #define BTA_GATTC_ADV_VSC_EVT         34 /* ADV VSC event */
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+#define BTA_GATTC_EXTENDED_ADV_ENB_EVT  35  /* Extended Enable ADV event */
+#define BTA_GATTC_EXTENDED_ADV_UPD_EVT  36  /* Extended Update parameter event */
+#endif
 
 typedef UINT8 tBTA_GATTC_EVT;
 
diff --git a/bta/include/bta_hf_client_api.h b/bta/include/bta_hf_client_api.h
index 82235fa..784d9ac 100644
--- a/bta/include/bta_hf_client_api.h
+++ b/bta/include/bta_hf_client_api.h
@@ -26,6 +26,7 @@
 #define BTA_HF_CLIENT_API_H
 
 #include "bta_api.h"
+#define SNIFF_DISABLE  0
 
 /*****************************************************************************
 **  Constants and data types
@@ -101,6 +102,8 @@
 #define BTA_HF_CLIENT_BSIR_EVT              19 /* in-band ring tone setting changed event */
 #define BTA_HF_CLIENT_BINP_EVT              20 /* binp number event */
 #define BTA_HF_CLIENT_RING_INDICATION       21 /* HF Client ring indication */
+#define BTA_HF_CLIENT_CGMI_EVT              22 /* AG manufacturer identification */
+#define BTA_HF_CLIENT_CGMM_EVT              23 /* AG manufacturer model */
 #define BTA_HF_CLIENT_DISABLE_EVT           30 /* HF Client disabled */
 
 typedef UINT8 tBTA_HF_CLIENT_EVT;
@@ -227,6 +230,20 @@
     UINT16                     value;
 } tBTA_HF_CLIENT_VAL;
 
+#define BTA_HF_CLIENT_MANUFACTURER_ID 2048
+/* data associated with BTA_HF_CLIENT_CGMI_EVT event */
+typedef struct
+{
+    char                       name[BTA_HF_CLIENT_MANUFACTURER_ID + 1];
+} tBTA_HF_CLIENT_CGMI;
+
+#define BTA_HF_CLIENT_MANUFACTURER_MODEL 2048
+/* data associated with BTA_HF_CLIENT_CGMI_EVT event */
+typedef struct
+{
+    char                       model[BTA_HF_CLIENT_MANUFACTURER_MODEL + 1];
+} tBTA_HF_CLIENT_CGMM;
+
 /* union of data associated with AG callback */
 typedef union
 {
@@ -241,10 +258,14 @@
     tBTA_HF_CLIENT_AT_RESULT        result;
     tBTA_HF_CLIENT_CLCC             clcc;
     tBTA_HF_CLIENT_CNUM             cnum;
+    tBTA_HF_CLIENT_CGMI             cgmi;
+    tBTA_HF_CLIENT_CGMM             cgmm;
 } tBTA_HF_CLIENT;
 
 typedef UINT32 tBTA_HF_CLIENT_FEAT;
 
+extern BOOLEAN is_sniff_disabled;
+
 /* HF Client callback */
 typedef void (tBTA_HF_CLIENT_CBACK)(tBTA_HF_CLIENT_EVT event, tBTA_HF_CLIENT *p_data);
 
diff --git a/bta/include/bta_hh_api.h b/bta/include/bta_hh_api.h
index d43e492..f55664d 100644
--- a/bta/include/bta_hh_api.h
+++ b/bta/include/bta_hh_api.h
@@ -40,6 +40,22 @@
 #define BTA_HH_SSR_MIN_TOUT_DEF     2
 #endif
 
+#ifndef BTA_HH_SSR_MAX_LATENCY_OPTIMAL
+#define BTA_HH_SSR_MAX_LATENCY_OPTIMAL  360 /* 225 ms*/
+#endif
+
+#ifndef BTA_HH_SSR_MAX_LATENCY_MIN_OPTIMAL
+#define BTA_HH_SSR_MAX_LATENCY_MIN_OPTIMAL  256 /* 160 ms*/
+#endif
+
+#ifndef BTA_HH_SSR_MAX_LATENCY_ZERO
+#define BTA_HH_SSR_MAX_LATENCY_ZERO     0
+#endif
+
+#ifndef BTA_HH_SSR_DISABLE_SSR
+#define BTA_HH_SSR_DISABLE_SSR     1
+#endif
+
 /* BTA HID Host callback events */
 #define BTA_HH_ENABLE_EVT       0       /* HH enabled */
 #define BTA_HH_DISABLE_EVT      1       /* HH disabled */
diff --git a/bta/include/bta_hh_co.h b/bta/include/bta_hh_co.h
old mode 100755
new mode 100644
index 940b3cc..3b72478
--- a/bta/include/bta_hh_co.h
+++ b/bta/include/bta_hh_co.h
@@ -76,6 +76,30 @@
 *******************************************************************************/
 extern void bta_hh_co_close(UINT8 dev_handle, UINT8 app_id);
 
+/*******************************************************************************
+**
+** Function         bta_hh_co_set_rpt_rsp
+**
+** Description      This callout function is executed by HH when Set Report Response is received
+**                      on Control Channel.
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_hh_co_set_rpt_rsp(UINT8 dev_handle, UINT8 status);
+
+/*******************************************************************************
+**
+** Function         bta_hh_co_get_rpt_rsp
+**
+** Description      This callout function is executed by HH when Get Report Response is received
+**                      on Control Channel.
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_hh_co_get_rpt_rsp(UINT8 dev_handle, UINT8 status, UINT8 *p_rpt, UINT16 len);
+
 #if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE)
 /*******************************************************************************
 **
diff --git a/bta/include/bta_jv_api.h b/bta/include/bta_jv_api.h
index f4999c5..9042f28 100644
--- a/bta/include/bta_jv_api.h
+++ b/bta/include/bta_jv_api.h
@@ -68,6 +68,9 @@
 #define BTA_JV_LAST_SERVICE_ID  BTA_LAST_JV_SERVICE_ID
 #define BTA_JV_NUM_SERVICE_ID   (BTA_LAST_JV_SERVICE_ID - BTA_FIRST_JV_SERVICE_ID + 1)
 
+/* Intermediate Idle timeout(s) for TX/RX*/
+#define BTA_JV_IDLE_TIMEOUT_MS 1000
+
 /* Discoverable modes */
 enum
 {
@@ -269,6 +272,7 @@
     tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
     UINT32          handle;     /* The connection handle */
     BD_ADDR         rem_bda;    /* The peer address */
+    UINT16          mtu;        /* peer mtu */
 } tBTA_JV_RFCOMM_OPEN;
 /* data associated with BTA_JV_RFCOMM_SRV_OPEN_EVT */
 typedef struct
@@ -277,6 +281,7 @@
     UINT32          handle;             /* The connection handle */
     UINT32          new_listen_handle;  /* The new listen handle */
     BD_ADDR         rem_bda;            /* The peer address */
+    UINT16          mtu;                /* peer mtu */
 } tBTA_JV_RFCOMM_SRV_OPEN;
 
 
diff --git a/bta/include/utl.h b/bta/include/utl.h
index c309ec9..cc7fa0c 100644
--- a/bta/include/utl.h
+++ b/bta/include/utl.h
@@ -75,6 +75,20 @@
 
 /*******************************************************************************
 **
+** Function         utl_str2int32
+**
+** Description      This utility function converts a character string to an
+**                  int32.  Acceptable values in string are 0-9.  If
+**                  invalid string or string value too large, -1 is returned.
+**
+**
+** Returns          int32_t value or -1 on error.
+**
+*******************************************************************************/
+extern INT32 utl_str2int32(const char *p_s);
+
+/*******************************************************************************
+**
 ** Function         utl_strucmp
 **
 ** Description      This utility function compares two strings in uppercase.
diff --git a/bta/jv/bta_jv_act.c b/bta/jv/bta_jv_act.c
index 3918fdf..68dd4f9 100644
--- a/bta/jv/bta_jv_act.c
+++ b/bta/jv/bta_jv_act.c
@@ -28,6 +28,7 @@
 #include <string.h>
 
 #include "osi/include/allocator.h"
+#include "btu.h"
 #include "bt_types.h"
 #include "bt_common.h"
 #include "utl.h"
@@ -49,7 +50,7 @@
 
 #include "osi/include/osi.h"
 
-
+extern fixed_queue_t *btu_general_alarm_queue;
 /* one of these exists for each client */
 struct fc_client {
     struct fc_client    *next_all_list;
@@ -413,9 +414,15 @@
 *******************************************************************************/
 static void bta_jv_clear_pm_cb(tBTA_JV_PM_CB *p_pm_cb, BOOLEAN close_conn)
 {
+    /* Ensure that timer is stopped */
+    alarm_cancel(p_pm_cb->idle_timer);
+
     /* needs to be called if registered with bta pm, otherwise we may run out of dm pm slots! */
     if (close_conn)
         bta_sys_conn_close(BTA_ID_JV, p_pm_cb->app_id, p_pm_cb->peer_bd_addr);
+    else
+        bta_jv_pm_state_change(p_pm_cb, BTA_JV_CONN_IDLE);
+
     p_pm_cb->state = BTA_JV_PM_FREE_ST;
     p_pm_cb->app_id = BTA_JV_PM_ALL;
     p_pm_cb->handle = BTA_JV_PM_HANDLE_CLEAR;
@@ -456,10 +463,6 @@
                     "app_id: 0x%x",__func__, jv_handle, i, bta_jv_cb.pm_cb[i].app_id);
             APPL_TRACE_API("%s, bd_counter = %d, "
                     "appid_counter = %d", __func__, bd_counter, appid_counter);
-            if (bd_counter > 1)
-            {
-                bta_jv_pm_conn_idle(&bta_jv_cb.pm_cb[i]);
-            }
 
             if (bd_counter <= 1 || (appid_counter <= 1))
             {
@@ -576,6 +579,9 @@
         bta_jv_cb.pm_cb[i].app_id = app_id;
         bdcpy(bta_jv_cb.pm_cb[i].peer_bd_addr, peer_bd_addr);
         bta_jv_cb.pm_cb[i].state = BTA_JV_PM_IDLE_ST;
+
+        bta_jv_cb.pm_cb[i].idle_timer = alarm_new("bta.jv_idle_timer");
+        APPL_TRACE_DEBUG("bta_jv_alloc_set_pm_profile_cb: %d, PM_cb: %p", i, &bta_jv_cb.pm_cb[i]);
         return &bta_jv_cb.pm_cb[i];
     }
     APPL_TRACE_WARNING("bta_jv_alloc_set_pm_profile_cb(jv_handle: 0x%x, app_id: %d) "
@@ -1026,6 +1032,10 @@
         bta_jv_pm_conn_idle(p_cb->p_pm_cb);
         break;
 
+    case GAP_EVT_TX_DONE:
+        bta_jv_pm_conn_idle(p_cb->p_pm_cb);
+        break;
+
     case GAP_EVT_CONN_CONGESTED:
     case GAP_EVT_CONN_UNCONGESTED:
         p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? TRUE : FALSE;
@@ -1115,7 +1125,8 @@
     }
 
     evt_data.handle = handle;
-    cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, (tBTA_JV *)&evt_data, cc->user_data);
+    if(cc->p_cback)
+        cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, (tBTA_JV *)&evt_data, cc->user_data);
 }
 
 
@@ -1196,6 +1207,10 @@
         bta_jv_pm_conn_idle(p_cb->p_pm_cb);
         break;
 
+    case GAP_EVT_TX_DONE:
+        bta_jv_pm_conn_idle(p_cb->p_pm_cb);
+        break;
+
     case GAP_EVT_CONN_CONGESTED:
     case GAP_EVT_CONN_UNCONGESTED:
         p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? TRUE : FALSE;
@@ -1280,7 +1295,8 @@
         p_cb->psm = ls->local_psm;
     }
 
-    ls->p_cback(BTA_JV_L2CAP_START_EVT, (tBTA_JV *)&evt_data, ls->user_data);
+    if(ls->p_cback)
+        ls->p_cback(BTA_JV_L2CAP_START_EVT, (tBTA_JV *)&evt_data, ls->user_data);
 }
 
 /*******************************************************************************
@@ -1309,7 +1325,8 @@
             evt_data.handle = p_cb->handle;
             evt_data.status = bta_jv_free_l2c_cb(p_cb);
             evt_data.async = FALSE;
-            p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data);
+            if(p_cback)
+                p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data, ls->user_data);
             break;
         }
     }
@@ -1438,13 +1455,17 @@
 {
     tBTA_JV_RFC_CB  *p_cb = bta_jv_rfc_port_to_cb(port_handle);
     tBTA_JV_PCB     *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
+    int ret = 0;
     APPL_TRACE_DEBUG("%s, p_cb:%p, p_pcb:%p, len:%d, type:%d", __func__, p_cb, p_pcb, len, type);
     if (p_pcb != NULL)
     {
         switch(type)
         {
             case DATA_CO_CALLBACK_TYPE_INCOMING:
-                return bta_co_rfc_data_incoming(p_pcb->user_data, (BT_HDR*)buf);
+                bta_jv_pm_conn_busy(p_pcb->p_pm_cb);
+                ret = bta_co_rfc_data_incoming(p_pcb->user_data, (BT_HDR*)buf);
+                bta_jv_pm_conn_idle(p_pcb->p_pm_cb);
+                return ret;
             case DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE:
                 return bta_co_rfc_data_outgoing_size(p_pcb->user_data, (int*)buf);
             case DATA_CO_CALLBACK_TYPE_OUTGOING:
@@ -1477,7 +1498,10 @@
     tBTA_JV_RFCOMM_CBACK *p_cback;  /* the callback function */
 
     APPL_TRACE_DEBUG( "bta_jv_port_mgmt_cl_cback:code:%d, port_handle%d", code, port_handle);
-    if(NULL == p_cb || NULL == p_cb->p_cback)
+    /* Fix for below Klockwork issue
+     * Pointer 'p_pcb' returned from call to function 'bta_jv_rfc_port_to_pcb' at line 1490
+     * may be NULL and may be dereferenced at line 1500*/
+    if(NULL == p_cb || NULL == p_cb->p_cback || NULL == p_pcb)
         return;
 
     APPL_TRACE_DEBUG( "bta_jv_port_mgmt_cl_cback code=%d port_handle:%d handle:%d",
@@ -1490,6 +1514,7 @@
         evt_data.rfc_open.handle = p_cb->handle;
         evt_data.rfc_open.status = BTA_JV_SUCCESS;
         bdcpy(evt_data.rfc_open.rem_bda, rem_bda);
+        evt_data.rfc_open.mtu = PORT_GetRemoteMtu(port_handle);
         p_pcb->state = BTA_JV_ST_CL_OPEN;
         p_cb->p_cback(BTA_JV_RFCOMM_OPEN_EVT, &evt_data, p_pcb->user_data);
     }
@@ -1528,8 +1553,11 @@
     tBTA_JV evt_data;
 
     APPL_TRACE_DEBUG( "bta_jv_port_event_cl_cback:%d", port_handle);
-    if (NULL == p_cb || NULL == p_cb->p_cback)
-        return;
+    /* Fix for below Klockwork issue
+     * Pointer 'p_pcb' returned from call to function 'bta_jv_rfc_port_to_pcb' at line 1547
+     * may be NULL and may be dereferenced at line 1554*/
+    if (NULL == p_cb || NULL == p_cb->p_cback || NULL == p_pcb)
+          return;
 
     APPL_TRACE_DEBUG( "bta_jv_port_event_cl_cback code=x%x port_handle:%d handle:%d",
         code, port_handle, p_cb->handle);
@@ -1709,12 +1737,12 @@
     BD_ADDR rem_bda;
     UINT16 lcid;
     APPL_TRACE_DEBUG("bta_jv_port_mgmt_sr_cback, code:%d, port_handle:%d", code, port_handle);
-    if (NULL == p_cb || NULL == p_cb->p_cback)
-    {
-        APPL_TRACE_ERROR("bta_jv_port_mgmt_sr_cback, p_cb:%p, p_cb->p_cback%p",
-                p_cb, p_cb ? p_cb->p_cback : NULL);
+    /* Fix for below Klockwork issue
+     * Pointer 'p_pcb' returned from call to function 'bta_jv_rfc_port_to_pcb' at line 1729
+     * may be NULL and may be dereferenced at line 1738*/
+    if (NULL == p_cb || NULL == p_cb->p_cback || NULL == p_pcb)
         return;
-    }
+
     void *user_data = p_pcb->user_data;
     APPL_TRACE_DEBUG( "bta_jv_port_mgmt_sr_cback code=%d port_handle:0x%x handle:0x%x, p_pcb:%p, user:%d",
         code, port_handle, p_cb->handle, p_pcb, p_pcb->user_data);
@@ -1726,6 +1754,7 @@
         evt_data.rfc_srv_open.handle = p_pcb->handle;
         evt_data.rfc_srv_open.status = BTA_JV_SUCCESS;
         bdcpy(evt_data.rfc_srv_open.rem_bda, rem_bda);
+        evt_data.rfc_srv_open.mtu = PORT_GetRemoteMtu(port_handle);
         tBTA_JV_PCB *p_pcb_new_listen  = bta_jv_add_rfc_port(p_cb, p_pcb);
         if (p_pcb_new_listen)
         {
@@ -1777,7 +1806,7 @@
     tBTA_JV_RFC_CB  *p_cb = bta_jv_rfc_port_to_cb(port_handle);
     tBTA_JV evt_data;
 
-    if (NULL == p_cb || NULL == p_cb->p_cback)
+    if (NULL == p_cb || NULL == p_cb->p_cback || NULL == p_pcb)
         return;
 
     APPL_TRACE_DEBUG( "bta_jv_port_event_sr_cback code=x%x port_handle:%d handle:%d",
@@ -2028,6 +2057,13 @@
     tBTA_JV_PCB     *p_pcb = wc->p_pcb;
     tBTA_JV_RFCOMM_WRITE    evt_data;
 
+
+    if (p_pcb->state == BTA_JV_ST_NONE) {
+        APPL_TRACE_ERROR("bta_jv_rfcomm_write : Incorect state (%d) to write data, returning",
+            p_pcb->state);
+        return;
+    }
+
     evt_data.status = BTA_JV_FAILURE;
     evt_data.handle = p_cb->handle;
     evt_data.req_id = wc->req_id;
@@ -2157,7 +2193,19 @@
 static void bta_jv_pm_conn_busy(tBTA_JV_PM_CB *p_cb)
 {
     if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST == p_cb->state))
-        bta_jv_pm_state_change(p_cb, BTA_JV_CONN_BUSY);
+    {
+        tBTM_PM_MODE    mode = BTM_PM_MD_ACTIVE;
+        if (BTM_ReadPowerMode(p_cb->peer_bd_addr, &mode) == BTM_SUCCESS) {
+            if (mode == BTM_PM_MD_SNIFF) {
+                bta_jv_pm_state_change(p_cb, BTA_JV_CONN_BUSY);
+            } else {
+                p_cb->state = BTA_JV_PM_BUSY_ST;
+                APPL_TRACE_DEBUG("bta_jv_pm_conn_busy:power mode: %d", mode);
+            }
+        } else {
+          bta_jv_pm_state_change(p_cb, BTA_JV_CONN_BUSY);
+        }
+    }
 }
 
 /*******************************************************************************
@@ -2173,8 +2221,15 @@
  *******************************************************************************/
 static void bta_jv_pm_conn_idle(tBTA_JV_PM_CB *p_cb)
 {
-    if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST != p_cb->state))
-        bta_jv_pm_state_change(p_cb, BTA_JV_CONN_IDLE);
+    if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST != p_cb->state)) {
+        APPL_TRACE_DEBUG("bta_jv_pm_conn_idle, p_cb: %p", p_cb);
+        p_cb->state = BTA_JV_PM_IDLE_ST;
+            // start intermediate idle timer for 1s
+        if (!alarm_is_scheduled(p_cb->idle_timer)) {
+            alarm_set_on_queue(p_cb->idle_timer, BTA_JV_IDLE_TIMEOUT_MS,
+                   bta_jv_idle_timeout_handler, p_cb, btu_general_alarm_queue);
+        }
+    }
 }
 
 /*******************************************************************************
@@ -2461,7 +2516,7 @@
         }
     }
 
-    if (call_init)
+    if (call_init && p_cback)
         p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &init_evt, user_data);
 
     //call this with lock taken so socket does not disappear from under us */
@@ -2488,10 +2543,15 @@
             return;
         }
     }
-
-    sock_cback = t->p_cback;
-    sock_user_data = t->user_data;
-    evt_data.le_data_ind.handle = t->id;
+    /* Fix for below klockwork issue
+     * Null pointer 't' that comes from line 2508
+     * may be dereferenced at line 2525*/
+    if (t)
+    {
+       sock_cback = t->p_cback;
+       sock_user_data = t->user_data;
+       evt_data.le_data_ind.handle = t->id;
+    }
     evt_data.le_data_ind.p_buf = p_buf;
 
     if (sock_cback)
@@ -2547,7 +2607,8 @@
     }
     if (call_init_f)
         cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &evt, cc->user_data);
-    t->init_called = TRUE;
+    if (t)
+        t->init_called = TRUE;
 }
 
 
@@ -2644,3 +2705,33 @@
     if (t)
         fcclient_free(t);
 }
+
+/*******************************************************************************
+**
+** Function         bta_jv_idle_timeout_handler
+**
+** Description      Bta JV specific idle timeout handler
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_jv_idle_timeout_handler(void *tle) {
+    tBTA_JV_PM_CB *p_cb = (tBTA_JV_PM_CB *)tle;;
+    APPL_TRACE_DEBUG("%s p_cb: %p", __func__, p_cb);
+
+    if (NULL != p_cb) {
+
+        tBTM_PM_MODE    mode = BTM_PM_MD_ACTIVE;
+        if (BTM_ReadPowerMode(p_cb->peer_bd_addr, &mode) == BTM_SUCCESS) {
+            if (mode == BTM_PM_MD_SNIFF) {
+                APPL_TRACE_WARNING("%s: %d", __func__, mode)
+                return;
+            }
+        } else {
+            APPL_TRACE_DEBUG("%s: Read power mode failed %d", __func__, mode);
+        }
+        bta_jv_pm_state_change(p_cb, BTA_JV_CONN_IDLE);
+    }
+}
+
diff --git a/bta/jv/bta_jv_int.h b/bta/jv/bta_jv_int.h
index 84580fa..5181196 100644
--- a/bta/jv/bta_jv_int.h
+++ b/bta/jv/bta_jv_int.h
@@ -29,6 +29,7 @@
 #include "bta_jv_api.h"
 #include "rfcdefs.h"
 #include "port_api.h"
+#include "osi/include/alarm.h"
 
 /*****************************************************************************
 **  Constants
@@ -102,6 +103,7 @@
     UINT8           state;      /* state: see above enum */
     tBTA_JV_PM_ID   app_id;     /* JV app specific id indicating power table to use */
     BD_ADDR         peer_bd_addr;    /* Peer BD address */
+    alarm_t         *idle_timer; /* intermediate idle timer for paricular scb */
 } tBTA_JV_PM_CB;
 
 enum
@@ -435,5 +437,6 @@
 extern void bta_jv_l2cap_stop_server_le (tBTA_JV_MSG *p_data);
 extern void bta_jv_l2cap_write_fixed (tBTA_JV_MSG *p_data);
 extern void bta_jv_l2cap_close_fixed (tBTA_JV_MSG *p_data);
+extern void bta_jv_idle_timeout_handler(void *tle);
 
 #endif /* BTA_JV_INT_H */
diff --git a/bta/pan/bta_pan_ci.c b/bta/pan/bta_pan_ci.c
index ec77e60..64c6776 100644
--- a/bta/pan/bta_pan_ci.c
+++ b/bta/pan/bta_pan_ci.c
@@ -194,6 +194,9 @@
 
     p_scb = bta_pan_scb_by_handle(handle);
 
+    if (p_scb == NULL)
+        return NULL;
+
     p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_scb->data_queue);
     if (p_buf != NULL)
     {
diff --git a/bta/pan/bta_pan_main.c b/bta/pan/bta_pan_main.c
index a766f2e..36fdbc9 100644
--- a/bta/pan/bta_pan_main.c
+++ b/bta/pan/bta_pan_main.c
@@ -214,12 +214,13 @@
     /* execute action functions */
     for (i = 0; i < BTA_PAN_ACTIONS; i++)
     {
-        if ((action = state_table[event][i]) != BTA_PAN_IGNORE)
+        if ((action = state_table[event][i]) < BTA_PAN_IGNORE)
         {
             (*bta_pan_action[action])(p_scb, p_data);
         }
         else
         {
+            APPL_TRACE_EVENT("action: %d", action);
             break;
         }
     }
diff --git a/bta/sys/bta_sys_main.c b/bta/sys/bta_sys_main.c
index af32cc9..6bb64c6 100644
--- a/bta/sys/bta_sys_main.c
+++ b/bta/sys/bta_sys_main.c
@@ -58,6 +58,7 @@
 /* TODO Hard-coded trace levels -  Needs to be configurable */
 UINT8 appl_trace_level = BT_TRACE_LEVEL_WARNING; //APPL_INITIAL_TRACE_LEVEL;
 UINT8 btif_trace_level = BT_TRACE_LEVEL_WARNING;
+UINT8 audio_latency_trace_level = BT_TRACE_LEVEL_WARNING;
 
 // Communication queue between btu_task and bta.
 extern fixed_queue_t *btu_bta_msg_queue;
@@ -225,7 +226,7 @@
     /* execute action functions */
     for (i = 0; i < BTA_SYS_ACTIONS; i++)
     {
-        if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_SYS_IGNORE)
+        if ((action = state_table[p_msg->event & 0x00ff][i]) < BTA_SYS_IGNORE)
         {
             (*bta_sys_action[action])( (tBTA_SYS_HW_MSG*) p_msg);
         }
diff --git a/bta/sys/utl.c b/bta/sys/utl.c
index fc3d7eb..e75e973 100644
--- a/bta/sys/utl.c
+++ b/bta/sys/utl.c
@@ -68,6 +68,46 @@
 
 /*******************************************************************************
 **
+** Function         utl_str2int32
+**
+** Description      This utility function converts a character string to an
+**                  int32.  Acceptable values in string are 0-9.  If invalid
+**                  string or string value too large, -1 is returned.  Leading
+**                  spaces are skipped.
+**
+**
+** Returns          int32_t value or -1 on error.
+**
+*******************************************************************************/
+INT32 utl_str2int32(const char *p_s)
+{
+    INT32   val = 0;
+
+    for (;*p_s == ' ' && *p_s != 0; p_s++);
+
+    if (*p_s == 0) return -1;
+
+    for (;;)
+    {
+        if ((*p_s < '0') || (*p_s > '9')) return -1;
+
+        val += (INT32) (*p_s++ - '0');
+
+        if (val > 65535) return -1;
+
+        if (*p_s == 0)
+        {
+            return val;
+        }
+        else
+        {
+            val *= 10;
+        }
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         utl_strucmp
 **
 ** Description      This utility function compares two strings in uppercase.
@@ -265,6 +305,7 @@
     {
         if(!(((p_s[i] >= '0') && (p_s[i] <= '9'))
             || (p_s[i] == '*') || (p_s[i] == '+') || (p_s[i] == '#') || (p_s[i] == ';')
+            || (p_s[i] == '-')
             || ((p_s[i] >= 'A') && (p_s[i] <= 'C'))
             || ((p_s[i] == 'p') || (p_s[i] == 'P')
             || (p_s[i] == 'w') || (p_s[i] == 'W'))))
diff --git a/btcore/src/module.c b/btcore/src/module.c
index 07b3dd0..ab7710a 100644
--- a/btcore/src/module.c
+++ b/btcore/src/module.c
@@ -33,7 +33,8 @@
 typedef enum {
   MODULE_STATE_NONE = 0,
   MODULE_STATE_INITIALIZED = 1,
-  MODULE_STATE_STARTED = 2
+  MODULE_STATE_STARTED = 2,
+  MODULE_STATE_STARTUP_ERROR = 3
 } module_state_t;
 
 static const size_t number_of_metadata_buckets = 42;
@@ -100,8 +101,8 @@
 
   LOG_INFO(LOG_TAG, "%s Starting module \"%s\"", __func__, module->name);
   if (!call_lifecycle_function(module->start_up)) {
-    LOG_ERROR(LOG_TAG, "%s Failed to start up module \"%s\"",
-              __func__, module->name);
+    LOG_ERROR(LOG_TAG, "%s failed to start up \"%s\"", __func__, module->name);
+    set_module_state(module, MODULE_STATE_STARTUP_ERROR);
     return false;
   }
   LOG_INFO(LOG_TAG, "%s Started module \"%s\"", __func__, module->name);
@@ -114,7 +115,6 @@
   assert(metadata != NULL);
   assert(module != NULL);
   module_state_t state = get_module_state(module);
-  assert(state <= MODULE_STATE_STARTED);
 
   // Only something to do if the module was actually started
   if (state < MODULE_STATE_STARTED)
diff --git a/btif/Android.mk b/btif/Android.mk
index d6b934d..cea6e80 100644
--- a/btif/Android.mk
+++ b/btif/Android.mk
@@ -65,7 +65,15 @@
   src/btif_storage.c \
   src/btif_uid.c \
   src/btif_util.c \
-  src/stack_manager.c
+  src/stack_manager.c \
+  src/btif_stack_log.c \
+  src/btif_rfcomm.c \
+  src/btif_mcap.c \
+  src/btif_l2cap.c \
+  src/btif_vendor.c \
+  src/btif_gatt_qual.c \
+  src/btif_gap.c \
+  src/btif_smp.c
 
 # Callouts
 btifCommonSrc += \
@@ -109,7 +117,18 @@
   $(LOCAL_PATH)/../utils/include \
   $(bluetooth_C_INCLUDES) \
   external/tinyxml2 \
-  external/zlib
+  external/zlib \
+  $(call include-path-for, audio-utils)
+
+ifneq ($(TARGET_SUPPORTS_WEARABLES),true)
+btifCommonIncludes += \
+   vendor/qcom/opensource/bluetooth/hal/include \
+   vendor/qcom/opensource/bluetooth/system_bt_ext
+else
+btifCommonIncludes += \
+   device/qcom/msm8909w/opensource/bluetooth/hal/include \
+   device/qcom/msm8909w/opensource/bluetooth/system_bt_ext
+endif
 
 # libbtif static library for target
 # ========================================================
@@ -126,6 +145,7 @@
 LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS)
 LOCAL_CPPFLAGS += $(bluetooth_CPPFLAGS)
 
+
 include $(BUILD_STATIC_LIBRARY)
 
 # btif unit tests for target
@@ -134,7 +154,7 @@
 LOCAL_C_INCLUDES := $(btifCommonIncludes)
 LOCAL_SRC_FILES := $(btifTestSrc)
 LOCAL_SHARED_LIBRARIES += liblog libhardware libhardware_legacy libcutils
-LOCAL_STATIC_LIBRARIES += libbtcore libbtif libosi
+LOCAL_STATIC_LIBRARIES += libbtcore libbtif libosi libbtdevice
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE := net_test_btif
 
diff --git a/btif/co/bta_ag_co.c b/btif/co/bta_ag_co.c
old mode 100755
new mode 100644
index e18cc9d..c50c128
--- a/btif/co/bta_ag_co.c
+++ b/btif/co/bta_ag_co.c
@@ -66,7 +66,9 @@
 void bta_ag_co_audio_state(UINT16 handle, UINT8 app_id, UINT8 state)
 #endif
 {
+#if (BLUETOOTH_QTI_SW == TRUE)
     BTIF_TRACE_DEBUG("bta_ag_co_audio_state: handle %d, state %d", handle, state);
+#else
     switch (state)
     {
     case SCO_STATE_OFF:
@@ -99,6 +101,7 @@
     APPL_TRACE_DEBUG("bta_ag_co_audio_state(handle %d, app_id: %d, state %d)", \
     handle, app_id, state);
 #endif
+#endif
 }
 
 
diff --git a/btif/co/bta_av_co.c b/btif/co/bta_av_co.c
index 76c8836..e6f480f 100644
--- a/btif/co/bta_av_co.c
+++ b/btif/co/bta_av_co.c
@@ -1,4 +1,9 @@
 /******************************************************************************
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a contribution.
+ ******************************************************************************/
+/******************************************************************************
  *
  *  Copyright (C) 2004-2012 Broadcom Corporation
  *
@@ -22,7 +27,7 @@
  *  BTIF.
  *
  ******************************************************************************/
-
+#include <cutils/properties.h>
 #include "string.h"
 #include "a2d_api.h"
 #include "a2d_sbc.h"
@@ -34,10 +39,19 @@
 
 #include "btif_media.h"
 #include "sbc_encoder.h"
+#include "btif_av.h"
 #include "btif_av_co.h"
 #include "btif_util.h"
 #include "osi/include/mutex.h"
+#include "device/include/interop.h"
 
+#include "bt_utils.h"
+#include "a2d_aptx.h"
+#include "a2d_aptx_hd.h"
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+#include "a2d_aac.h"
+#include "bta_av_aac.h"
+#endif
 
 /*****************************************************************************
  **  Constants
@@ -63,7 +77,11 @@
 #define BTA_AV_CO_SBC_MIN_BITPOOL_OFF  5
 #define BTA_AV_CO_SBC_MAX_BITPOOL_OFF  6
 
+#ifdef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
+#define BTA_AV_CO_SBC_MAX_BITPOOL  51
+#else
 #define BTA_AV_CO_SBC_MAX_BITPOOL  53
+#endif
 
 /* SCMS-T protect info */
 const UINT8 bta_av_co_cp_scmst[BTA_AV_CP_INFO_LEN] = "\x02\x02\x00";
@@ -71,11 +89,15 @@
 /* SBC SRC codec capabilities */
 const tA2D_SBC_CIE bta_av_co_sbc_caps =
 {
+#ifdef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
+    (A2D_SBC_IE_SAMP_FREQ_48), /* samp_freq */
+#else
     (A2D_SBC_IE_SAMP_FREQ_44), /* samp_freq */
-    (A2D_SBC_IE_CH_MD_JOINT), /* ch_mode */
-    (A2D_SBC_IE_BLOCKS_16), /* block_len */
-    (A2D_SBC_IE_SUBBAND_8), /* num_subbands */
-    (A2D_SBC_IE_ALLOC_MD_L), /* alloc_mthd */
+#endif
+    (A2D_SBC_IE_CH_MD_MONO | A2D_SBC_IE_CH_MD_STEREO | A2D_SBC_IE_CH_MD_JOINT | A2D_SBC_IE_CH_MD_DUAL), /* ch_mode */
+    (A2D_SBC_IE_BLOCKS_16 | A2D_SBC_IE_BLOCKS_12 | A2D_SBC_IE_BLOCKS_8 | A2D_SBC_IE_BLOCKS_4), /* block_len */
+    (A2D_SBC_IE_SUBBAND_4 | A2D_SBC_IE_SUBBAND_8), /* num_subbands */
+    (A2D_SBC_IE_ALLOC_MD_L | A2D_SBC_IE_ALLOC_MD_S), /* alloc_mthd */
     BTA_AV_CO_SBC_MAX_BITPOOL, /* max_bitpool */
     A2D_SBC_IE_MIN_BITPOOL /* min_bitpool */
 };
@@ -93,9 +115,18 @@
 };
 
 #if !defined(BTIF_AV_SBC_DEFAULT_SAMP_FREQ)
+#ifdef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
+#define BTIF_AV_SBC_DEFAULT_SAMP_FREQ A2D_SBC_IE_SAMP_FREQ_48
+#else
 #define BTIF_AV_SBC_DEFAULT_SAMP_FREQ A2D_SBC_IE_SAMP_FREQ_44
 #endif
+#endif
 
+/* A2dp offload capabilities */
+#define SBC    0
+#define APTX   1
+#define AAC    2
+#define APTXHD 3
 /* Default SBC codec configuration */
 const tA2D_SBC_CIE btif_av_sbc_default_config =
 {
@@ -108,6 +139,96 @@
     A2D_SBC_IE_MIN_BITPOOL          /* min_bitpool */
 };
 
+const tA2D_APTX_CIE bta_av_co_aptx_caps =
+{
+    A2D_APTX_VENDOR_ID,
+    A2D_APTX_CODEC_ID_BLUETOOTH,
+#ifndef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
+    A2D_APTX_SAMPLERATE_44100,
+#else
+    A2D_APTX_SAMPLERATE_48000,
+#endif
+    A2D_APTX_CHANNELS_STEREO,
+    A2D_APTX_FUTURE_1,
+    A2D_APTX_FUTURE_2
+};
+
+/* Default aptX codec configuration */
+const tA2D_APTX_CIE btif_av_aptx_default_config =
+{
+    A2D_APTX_VENDOR_ID,
+    A2D_APTX_CODEC_ID_BLUETOOTH,
+#ifndef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
+    A2D_APTX_SAMPLERATE_44100,
+#else
+    A2D_APTX_SAMPLERATE_48000,
+#endif
+    A2D_APTX_CHANNELS_STEREO,
+    A2D_APTX_FUTURE_1,
+    A2D_APTX_FUTURE_2
+};
+
+const tA2D_APTX_HD_CIE bta_av_co_aptx_hd_caps =
+{
+    A2D_APTX_HD_VENDOR_ID,
+    A2D_APTX_HD_CODEC_ID_BLUETOOTH,
+#ifndef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
+    A2D_APTX_HD_SAMPLERATE_44100,
+#else
+    A2D_APTX_HD_SAMPLERATE_48000,
+#endif
+    A2D_APTX_HD_CHANNELS_STEREO,
+    A2D_APTX_HD_ACL_SPRINT_RESERVED0,
+    A2D_APTX_HD_ACL_SPRINT_RESERVED1,
+    A2D_APTX_HD_ACL_SPRINT_RESERVED2,
+    A2D_APTX_HD_ACL_SPRINT_RESERVED3
+};
+
+/* Default aptX_hd codec configuration */
+const tA2D_APTX_HD_CIE btif_av_aptx_hd_default_config =
+{
+    A2D_APTX_HD_VENDOR_ID,
+    A2D_APTX_HD_CODEC_ID_BLUETOOTH,
+#ifndef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
+    A2D_APTX_HD_SAMPLERATE_44100,
+#else
+    A2D_APTX_HD_SAMPLERATE_48000,
+#endif
+    A2D_APTX_HD_CHANNELS_STEREO,
+    A2D_APTX_HD_ACL_SPRINT_RESERVED0,
+    A2D_APTX_HD_ACL_SPRINT_RESERVED1,
+    A2D_APTX_HD_ACL_SPRINT_RESERVED2,
+    A2D_APTX_HD_ACL_SPRINT_RESERVED3
+};
+
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+const tA2D_AAC_CIE bta_av_co_aac_caps =
+{
+    (A2D_AAC_IE_OBJ_TYPE_MPEG_2_AAC_LC), /* obj type */
+#ifndef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
+    (A2D_AAC_IE_SAMP_FREQ_44100),
+#else
+    (A2D_AAC_IE_SAMP_FREQ_48000),
+#endif
+    (A2D_AAC_IE_CHANNELS_1 | A2D_AAC_IE_CHANNELS_2 ), /* channels  */
+    BTIF_AAC_DEFAULT_BIT_RATE,      /* bit rate */
+    A2D_AAC_IE_VBR_NOT_SUPP  /* variable bit rate */
+};
+
+/* Default AAC codec configuration */
+const tA2D_AAC_CIE btif_av_aac_default_config =
+{
+    A2D_AAC_IE_OBJ_TYPE_MPEG_2_AAC_LC,  /* obj type */
+#ifndef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
+    A2D_AAC_IE_SAMP_FREQ_44100,         /* samp_freq */
+#else
+    A2D_AAC_IE_SAMP_FREQ_48000,         /* samp_freq */
+#endif
+    A2D_AAC_IE_CHANNELS_2,              /* channels  */
+    BTIF_AAC_DEFAULT_BIT_RATE,      /* bit rate */
+    A2D_AAC_IE_VBR_NOT_SUPP
+};
+#endif
 
 /*****************************************************************************
 **  Local data
@@ -125,8 +246,10 @@
 typedef struct
 {
     BD_ADDR         addr;               /* address of audio/video peer */
-    tBTA_AV_CO_SINK snks[BTIF_SV_AV_AA_SEP_INDEX]; /* array of supported sinks */
-    tBTA_AV_CO_SINK srcs[BTIF_SV_AV_AA_SEP_INDEX]; /* array of supported srcs */
+    /* array of supported sinks */
+    tBTA_AV_CO_SINK snks[BTIF_SV_AV_AA_SRC_SEP_INDEX - BTIF_SV_AV_AA_SBC_INDEX];
+    /* array of supported srcs */
+    tBTA_AV_CO_SINK srcs[BTIF_SV_AV_AA_SNK_SEP_INDEX - BTIF_SV_AV_AA_SBC_SINK_INDEX];
     UINT8           num_snks;           /* total number of sinks at peer */
     UINT8           num_srcs;           /* total number of srcs at peer */
     UINT8           num_seps;           /* total number of seids at peer */
@@ -156,9 +279,19 @@
     /* Connected peer information */
     tBTA_AV_CO_PEER peers[BTA_AV_NUM_STRS];
     /* Current codec configuration - access to this variable must be protected */
-    tBTIF_AV_CODEC_INFO codec_cfg;
-    tBTIF_AV_CODEC_INFO codec_cfg_setconfig; /* remote peer setconfig preference */
-
+    tBTIF_AV_CODEC_INFO* codec_cfg;
+    tBTIF_AV_CODEC_INFO* codec_cfg_setconfig; /* remote peer setconfig preference */
+    UINT8 current_codec_id;
+    tBTIF_AV_CODEC_INFO codec_cfg_sbc;
+    tBTIF_AV_CODEC_INFO codec_cfg_sbc_setconfig; /* remote peer setconfig preference (SBC) */
+    tBTIF_AV_CODEC_INFO codec_cfg_aptx;
+    tBTIF_AV_CODEC_INFO codec_cfg_aptx_setconfig; /* remote peer setconfig preference (aptX)*/
+    tBTIF_AV_CODEC_INFO codec_cfg_aptx_hd;
+    tBTIF_AV_CODEC_INFO codec_cfg_aptx_hd_setconfig; /* remote peer setconfig preference (aptX HD) */
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    tBTIF_AV_CODEC_INFO codec_cfg_aac;
+    tBTIF_AV_CODEC_INFO codec_cfg_aac_setconfig; /* remote peer setconfig preference (AAC)*/
+#endif
     tBTA_AV_CO_CP cp;
 } tBTA_AV_CO_CB;
 
@@ -169,13 +302,17 @@
 static void bta_av_co_audio_peer_reset_config(tBTA_AV_CO_PEER *p_peer);
 static BOOLEAN bta_av_co_cp_is_scmst(const UINT8 *p_protectinfo);
 static BOOLEAN bta_av_co_audio_sink_has_scmst(const tBTA_AV_CO_SINK *p_sink);
-static BOOLEAN bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_snk_index);
+static BOOLEAN bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_snk_index, UINT8 *p_codec_type);
 static BOOLEAN bta_av_co_audio_media_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg);
 static BOOLEAN bta_av_co_audio_sink_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg);
 static BOOLEAN bta_av_co_audio_peer_src_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_src_index);
-
-
-
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+extern BOOLEAN btif_av_is_codec_offload_supported(int codec);
+#else
+#define btif_av_is_codec_offload_supported(codec) (0)
+#endif
+extern BOOLEAN btif_av_is_offload_supported();
+extern BOOLEAN bt_split_a2dp_enabled;
 /*******************************************************************************
  **
  ** Function         bta_av_co_cp_is_active
@@ -287,7 +424,7 @@
     *p_protect_info = 0;
 
     /* reset remote preference through setconfig */
-    bta_av_co_cb.codec_cfg_setconfig.id = BTIF_AV_CODEC_NONE;
+    bta_av_co_cb.codec_cfg_setconfig = NULL;
 
     switch (index)
     {
@@ -311,6 +448,28 @@
 
         /* Codec is valid */
         return TRUE;
+
+    case BTIF_SV_AV_AA_APTX_INDEX:
+        APPL_TRACE_DEBUG("%s aptX", __func__);
+        /* Set up for aptX codec */
+        *p_codec_type = A2D_NON_A2DP_MEDIA_CT;
+        A2D_BldAptxInfo(AVDT_MEDIA_AUDIO, (tA2D_APTX_CIE *) &bta_av_co_aptx_caps, p_codec_info);
+        return TRUE;
+
+    case BTIF_SV_AV_AA_APTX_HD_INDEX:
+        APPL_TRACE_DEBUG("%s aptX HD", __func__);
+        /* Set up for aptX HD codec */
+        *p_codec_type = A2D_NON_A2DP_MEDIA_CT;
+        A2D_BldAptx_hdInfo(AVDT_MEDIA_AUDIO, (tA2D_APTX_HD_CIE *) &bta_av_co_aptx_hd_caps, p_codec_info);
+        return TRUE;
+
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    case BTIF_SV_AV_AA_AAC_INDEX:
+        APPL_TRACE_DEBUG("%s AAC", __func__);
+        *p_codec_type = BTA_AV_CODEC_M24;
+        A2D_BldAacInfo(AVDT_MEDIA_AUDIO, (tA2D_AAC_CIE *) &bta_av_co_aac_caps ,p_codec_info);
+        return TRUE;
+#endif
 #if (BTA_AV_SINK_INCLUDED == TRUE)
     case BTIF_SV_AV_AA_SBC_SINK_INDEX:
         *p_codec_type = BTA_AV_CODEC_SBC;
@@ -623,7 +782,28 @@
     case BTA_AV_CODEC_SBC:
         supported = TRUE;
         break;
+    case A2D_NON_A2DP_MEDIA_CT:
+    {
+        UINT16 codecId = ((tA2D_APTX_CIE*)(&p_codec_info[BTA_AV_CFG_START_IDX]))->codecId;
+        UINT32 vendorId = ((tA2D_APTX_CIE*)(&p_codec_info[BTA_AV_CFG_START_IDX]))->vendorId;
+        APPL_TRACE_DEBUG("%s codecId = %d", __func__, codecId );
+        APPL_TRACE_DEBUG("%s vendorId = %x", __func__, vendorId );
 
+        if (codecId ==  A2D_APTX_CODEC_ID_BLUETOOTH && vendorId == A2D_APTX_VENDOR_ID) {
+            /* aptX */
+            supported = TRUE;
+        } else if (codecId ==  A2D_APTX_HD_CODEC_ID_BLUETOOTH && vendorId == A2D_APTX_HD_VENDOR_ID) {
+            /*	aptX HD	*/
+            supported = TRUE;
+        }
+        break;
+    }
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    case BTA_AV_CODEC_M24:
+        APPL_TRACE_DEBUG("%s: AAC is supported", __func__);
+        supported = TRUE;
+        break;
+#endif
     default:
         break;
     }
@@ -633,13 +813,21 @@
         /* If there is room for a new one */
         if (p_peer->num_sup_snks < BTA_AV_CO_NUM_ELEMENTS(p_peer->snks))
         {
+            int i = 0;
             p_sink = &p_peer->snks[p_peer->num_sup_snks++];
 
             APPL_TRACE_DEBUG("bta_av_co_audio_getconfig saved caps[%x:%x:%x:%x:%x:%x]",
                     p_codec_info[1], p_codec_info[2], p_codec_info[3],
                     p_codec_info[4], p_codec_info[5], p_codec_info[6]);
 
-            memcpy(p_sink->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
+            for (i = 0 ; i < AVDT_CODEC_SIZE; i++)
+                APPL_TRACE_DEBUG("%s p_codec_info[%d]: %x", __func__, i,  p_codec_info[i]);
+
+            if (codec_type == A2D_NON_A2DP_MEDIA_CT)
+                memcpy(p_sink->codec_caps, &p_codec_info[BTA_AV_CFG_START_IDX], AVDT_CODEC_SIZE);
+            else
+                memcpy(p_sink->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
+
             p_sink->codec_type = codec_type;
             p_sink->sep_info_idx = *p_sep_info_idx;
             p_sink->seid = seid;
@@ -662,7 +850,7 @@
         mutex_global_lock();
 
         /* Find a sink that matches the codec config */
-        if (bta_av_co_audio_peer_supports_codec(p_peer, &index))
+        if (bta_av_co_audio_peer_supports_codec(p_peer, &index, NULL))
         {
             /* stop fetching caps once we retrieved a supported codec */
             if (p_peer->acp)
@@ -676,10 +864,14 @@
             /* Build the codec configuration for this sink */
             if (bta_av_co_audio_codec_build_config(p_sink->codec_caps, codec_cfg))
             {
+                int i = 0;
                 APPL_TRACE_DEBUG("bta_av_co_audio_getconfig reconfig p_codec_info[%x:%x:%x:%x:%x:%x]",
                         codec_cfg[1], codec_cfg[2], codec_cfg[3],
                         codec_cfg[4], codec_cfg[5], codec_cfg[6]);
 
+                for (i = 0 ; i < AVDT_CODEC_SIZE; i++)
+                    APPL_TRACE_DEBUG("%s p_codec_info[%d]: %x", __func__, i,  p_codec_info[i]);
+
                 /* Save the new configuration */
                 p_peer->p_snk = p_sink;
                 memcpy(p_peer->codec_cfg, codec_cfg, AVDT_CODEC_SIZE);
@@ -751,7 +943,7 @@
 
     FUNC_TRACE();
 
-    APPL_TRACE_DEBUG("bta_av_co_audio_setconfig p_codec_info[%x:%x:%x:%x:%x:%x]",
+    APPL_TRACE_IMP("bta_av_co_audio_setconfig p_codec_info[%x:%x:%x:%x:%x:%x]",
             p_codec_info[1], p_codec_info[2], p_codec_info[3],
             p_codec_info[4], p_codec_info[5], p_codec_info[6]);
     APPL_TRACE_DEBUG("num_protect:0x%02x protect_info:0x%02x%02x%02x",
@@ -817,10 +1009,10 @@
             mutex_global_lock();
 
             /* Check if the configuration matches the current codec config */
-            switch (bta_av_co_cb.codec_cfg.id)
+            switch (codec_type)
             {
             case BTIF_AV_CODEC_SBC:
-                if ((codec_type != BTA_AV_CODEC_SBC) || memcmp(p_codec_info, bta_av_co_cb.codec_cfg.info, 5))
+                if ((codec_type != BTA_AV_CODEC_SBC) || memcmp(p_codec_info, bta_av_co_cb.codec_cfg_sbc.info, 5))
                 {
                     recfg_needed = TRUE;
                 }
@@ -831,24 +1023,93 @@
 
                 /* if remote side requests a restricted notify sinks preferred bitpool range as all other params are
                    already checked for validify */
+                APPL_TRACE_DEBUG("%s SBC", __func__);
                 APPL_TRACE_EVENT("remote peer setconfig bitpool range [%d:%d]",
                    p_codec_info[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
                    p_codec_info[BTA_AV_CO_SBC_MAX_BITPOOL_OFF] );
 
-                bta_av_co_cb.codec_cfg_setconfig.id = BTIF_AV_CODEC_SBC;
-                memcpy(bta_av_co_cb.codec_cfg_setconfig.info, p_codec_info, AVDT_CODEC_SIZE);
+                bta_av_co_cb.codec_cfg_sbc_setconfig.id = BTIF_AV_CODEC_SBC;
+                memcpy(bta_av_co_cb.codec_cfg_sbc_setconfig.info, p_codec_info, AVDT_CODEC_SIZE);
+                bta_av_co_cb.codec_cfg_setconfig = &bta_av_co_cb.codec_cfg_sbc_setconfig;
+                memcpy(bta_av_co_cb.codec_cfg_sbc.info, p_codec_info, AVDT_CODEC_SIZE);
+                memcpy(bta_av_co_cb.codec_cfg->info, p_codec_info, AVDT_CODEC_SIZE);
                 if(AVDT_TSEP_SNK == t_local_sep)
                 {
                     /* If Peer is SRC, and our cfg subset matches with what is requested by peer, then
                                          just accept what peer wants */
-                    memcpy(bta_av_co_cb.codec_cfg.info, p_codec_info, AVDT_CODEC_SIZE);
                     recfg_needed = FALSE;
                 }
                 break;
 
+            case A2D_NON_A2DP_MEDIA_CT:
+            {
+                UINT16 codecId;
+                UINT32 vendorId;
+                codecId = ((tA2D_APTX_CIE*)(&p_codec_info[BTA_AV_CFG_START_IDX]))->codecId;
+                vendorId = ((tA2D_APTX_CIE*)(&p_codec_info[BTA_AV_CFG_START_IDX]))->vendorId;
+                APPL_TRACE_DEBUG("%s codec_type = %x", __func__, codec_type);
+                APPL_TRACE_DEBUG("%s codecId = %d", __func__, codecId);
+                APPL_TRACE_DEBUG("%s vendorId = %x", __func__, vendorId);
 
+                if ( (codec_type != A2D_NON_A2DP_MEDIA_CT) ||
+                    ( (codecId != A2D_APTX_CODEC_ID_BLUETOOTH) &&
+                    (codecId != A2D_APTX_HD_CODEC_ID_BLUETOOTH) )
+                    || ((vendorId != A2D_APTX_VENDOR_ID) && (vendorId != A2D_APTX_HD_VENDOR_ID)) ||
+                    (memcmp(p_codec_info, bta_av_co_cb.codec_cfg_aptx.info, 5) &&
+                     memcmp(p_codec_info, bta_av_co_cb.codec_cfg_aptx_hd.info, 5)) )
+                {
+                    APPL_TRACE_DEBUG("%s recfg_needed", __func__);
+                    recfg_needed = TRUE;
+                }
+                else if ((num_protect == 1) && (!bta_av_co_cb.cp.active))
+                {
+                    APPL_TRACE_DEBUG("%s recfg_needed", __func__);
+                    recfg_needed = TRUE;
+                }
+
+                if ((codecId == A2D_APTX_CODEC_ID_BLUETOOTH) && (vendorId == A2D_APTX_VENDOR_ID)) {
+                    APPL_TRACE_DEBUG("%s aptX", __func__);
+                    bta_av_co_cb.codec_cfg_aptx_setconfig.id = A2D_NON_A2DP_MEDIA_CT;
+                    memcpy(bta_av_co_cb.codec_cfg_aptx_setconfig.info, p_codec_info, AVDT_CODEC_SIZE);
+                    bta_av_co_cb.codec_cfg_setconfig = &bta_av_co_cb.codec_cfg_aptx_setconfig;
+                } else if ((codecId == A2D_APTX_HD_CODEC_ID_BLUETOOTH) && (vendorId == A2D_APTX_HD_VENDOR_ID)) {
+                    APPL_TRACE_DEBUG("%s aptX HD", __func__);
+                    bta_av_co_cb.codec_cfg_aptx_hd_setconfig.id = A2D_NON_A2DP_MEDIA_CT;
+                    memcpy(bta_av_co_cb.codec_cfg_aptx_hd_setconfig.info, p_codec_info, AVDT_CODEC_SIZE);
+                    bta_av_co_cb.codec_cfg_setconfig = &bta_av_co_cb.codec_cfg_aptx_hd_setconfig;
+                }
+                break;
+             }
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+            case BTA_AV_CODEC_M24:
+            {
+                tA2D_AAC_CIE p_aac_cie;
+                A2D_ParsAacInfo(&p_aac_cie, p_codec_info, FALSE);
+                APPL_TRACE_ERROR("%s p_aac_cie->bitrate = %x",__func__, p_aac_cie.bit_rate);
+                if ((codec_type != BTA_AV_CODEC_M24) ||
+                        memcmp(p_codec_info, bta_av_co_cb.codec_cfg_aac.info, 5))
+                {
+                    recfg_needed = TRUE;
+                }
+                else if (p_aac_cie.bit_rate == 0 || p_aac_cie.bit_rate < BTIF_AAC_MIN_BITRATE)
+                {
+                    recfg_needed = TRUE;
+                }
+                else if ((num_protect == 1) && (!bta_av_co_cb.cp.active))
+                {
+                    recfg_needed = TRUE;
+                }
+
+                APPL_TRACE_DEBUG("%s AAC", __func__);
+                bta_av_co_cb.codec_cfg_aac_setconfig.id = BTIF_AV_CODEC_M24;
+                memcpy(bta_av_co_cb.codec_cfg_aac_setconfig.info, p_codec_info, AVDT_CODEC_SIZE);
+                bta_av_co_cb.codec_cfg_setconfig = &bta_av_co_cb.codec_cfg_aac_setconfig;
+
+                APPL_TRACE_DEBUG("%s codec_type = %x", __func__, codec_type);
+            } break;
+#endif
             default:
-                APPL_TRACE_ERROR("bta_av_co_audio_setconfig unsupported cid %d", bta_av_co_cb.codec_cfg.id);
+                APPL_TRACE_ERROR("bta_av_co_audio_setconfig unsupported cid %d", bta_av_co_cb.codec_cfg->id);
                 recfg_needed = TRUE;
                 break;
             }
@@ -864,7 +1125,7 @@
 
     if (status != A2D_SUCCESS)
     {
-        APPL_TRACE_DEBUG("bta_av_co_audio_setconfig reject s=%d c=%d", status, category);
+        APPL_TRACE_ERROR("bta_av_co_audio_setconfig reject s=%d c=%d", status, category);
 
         /* Call call-in rejecting the configuration */
         bta_av_ci_setconfig(hndl, status, category, 0, NULL, FALSE, avdt_handle);
@@ -951,7 +1212,7 @@
     }
 
     /* reset remote preference through setconfig */
-    bta_av_co_cb.codec_cfg_setconfig.id = BTIF_AV_CODEC_NONE;
+    bta_av_co_cb.codec_cfg_setconfig = NULL;
 }
 
 /*******************************************************************************
@@ -969,14 +1230,21 @@
                            UINT8 *p_codec_info, BOOLEAN *p_no_rtp_hdr)
 {
     UNUSED(hndl);
-    UNUSED(codec_type);
-    UNUSED(p_codec_info);
-    UNUSED(p_no_rtp_hdr);
 
     FUNC_TRACE();
 
     APPL_TRACE_DEBUG("bta_av_co_audio_start");
 
+    if (codec_type == A2D_NON_A2DP_MEDIA_CT) {
+        UINT16 codecId = ((tA2D_APTX_CIE*)(&p_codec_info[BTA_AV_CFG_START_IDX]))->codecId;
+        UINT32 vendorId = ((tA2D_APTX_CIE*)(&p_codec_info[BTA_AV_CFG_START_IDX]))->vendorId;
+
+        // for aptX, we only add RTP hdr along with CP
+        if (codecId == A2D_APTX_CODEC_ID_BLUETOOTH && vendorId == A2D_APTX_VENDOR_ID) {
+            if (!bta_av_co_cb.cp.active)
+                *p_no_rtp_hdr = TRUE;
+        }
+    }
 }
 
 /*******************************************************************************
@@ -1034,8 +1302,10 @@
             /* Set up packet header */
             bta_av_sbc_bld_hdr(p_buf, p_buf->layer_specific);
             break;
-
-
+        case A2D_NON_A2DP_MEDIA_CT:
+            /* Retrieve the timestamp information from the media packet */
+            *p_timestamp = *((UINT32 *) (p_buf + 1));
+            break;
         default:
             APPL_TRACE_ERROR("bta_av_co_audio_src_data_path Unsupported codec type (%d)", codec_type);
             break;
@@ -1107,26 +1377,69 @@
 static BOOLEAN bta_av_co_audio_codec_build_config(const UINT8 *p_codec_caps, UINT8 *p_codec_cfg)
 {
     FUNC_TRACE();
+    tA2D_AAC_CIE peer_aac_cfg;
+    tA2D_AAC_CIE aac_cfg_selected;
 
     memset(p_codec_cfg, 0, AVDT_CODEC_SIZE);
 
-    switch (bta_av_co_cb.codec_cfg.id)
+    switch (bta_av_co_cb.codec_cfg->id)
     {
     case BTIF_AV_CODEC_SBC:
         /*  only copy the relevant portions for this codec to avoid issues when
             comparing codec configs covering larger codec sets than SBC (7 bytes) */
-        memcpy(p_codec_cfg, bta_av_co_cb.codec_cfg.info, BTA_AV_CO_SBC_MAX_BITPOOL_OFF+1);
+        memcpy(p_codec_cfg, bta_av_co_cb.codec_cfg->info, BTA_AV_CO_SBC_MAX_BITPOOL_OFF+1);
 
         /* Update the bit pool boundaries with the codec capabilities */
         p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF] = p_codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF];
         p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF] = p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF];
 
+        APPL_TRACE_DEBUG("%s SBC", __func__);
         APPL_TRACE_EVENT("bta_av_co_audio_codec_build_config : bitpool min %d, max %d",
                     p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
                     p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]);
         break;
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    case BTIF_AV_CODEC_M24:
+        /*  only copy the relevant portions for this codec to avoid issues when
+            comparing codec configs covering larger codec sets than SBC (7 bytes) */
+        A2D_ParsAacInfo (&peer_aac_cfg ,(UINT8*)p_codec_caps, FALSE);
+        A2D_ParsAacInfo (&aac_cfg_selected ,bta_av_co_cb.codec_cfg->info, FALSE);
+
+        if (peer_aac_cfg.bit_rate != 0 && peer_aac_cfg.bit_rate >= BTIF_AAC_MIN_BITRATE)
+        {
+            aac_cfg_selected.bit_rate =
+                            BTA_AV_CO_MIN(peer_aac_cfg.bit_rate,
+                                          aac_cfg_selected.bit_rate);
+            //update with new value
+            A2D_BldAacInfo (AVDT_MEDIA_AUDIO, &aac_cfg_selected, bta_av_co_cb.codec_cfg->info);
+        }
+        APPL_TRACE_EVENT("%s AAC bitrate selected %d", __func__,
+                                      aac_cfg_selected.bit_rate);
+        memcpy(p_codec_cfg, bta_av_co_cb.codec_cfg->info, A2D_AAC_INFO_LEN+1);
+        APPL_TRACE_DEBUG("%s AAC", __func__);
+        break;
+#endif
+    case A2D_NON_A2DP_MEDIA_CT:
+    {
+        UINT16 codecId;
+        UINT16 vendorId;
+        codecId = ((tA2D_APTX_CIE*)p_codec_caps)->codecId;
+        vendorId = ((tA2D_APTX_CIE*)p_codec_caps)->vendorId;
+        APPL_TRACE_DEBUG("%s codecId = %d", __func__, codecId);
+        APPL_TRACE_DEBUG("%s vendorId = %x", __func__, vendorId);
+
+        if ((codecId == A2D_APTX_CODEC_ID_BLUETOOTH) && (vendorId == A2D_APTX_VENDOR_ID)) {
+            memcpy(p_codec_cfg, bta_av_co_cb.codec_cfg->info, A2D_APTX_CODEC_LEN+1);
+            APPL_TRACE_DEBUG("%s aptX",__func__);
+        } else if ((codecId == A2D_APTX_HD_CODEC_ID_BLUETOOTH) && (vendorId == A2D_APTX_HD_VENDOR_ID)) {
+            memcpy(p_codec_cfg, bta_av_co_cb.codec_cfg->info, A2D_APTX_HD_CODEC_LEN+1);
+            APPL_TRACE_DEBUG("%s aptX HD",__func__);
+        }
+        break;
+    }
+
     default:
-        APPL_TRACE_ERROR("bta_av_co_audio_codec_build_config: unsupported codec id %d", bta_av_co_cb.codec_cfg.id);
+        APPL_TRACE_ERROR("bta_av_co_audio_codec_build_config: unsupported codec id %d", bta_av_co_cb.codec_cfg->id);
         return FALSE;
         break;
     }
@@ -1168,8 +1481,71 @@
             return FALSE;
         }
         break;
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+        /* in case of Sink we have to match if Src Cap is a subset of ours */
+    case BTA_AV_CODEC_M24:
+    {
+        tBTIF_AV_CODEC_INFO *p_local_aac_cfg = (tBTIF_AV_CODEC_INFO*)p_codec_cfg;
+        tA2D_AAC_CIE p_local_aac_caps;
+        tA2D_AAC_CIE p_snk_aac_caps;
 
+        if (A2D_ParsAacInfo(&p_local_aac_caps, (UINT8*)p_local_aac_cfg, FALSE) != A2D_SUCCESS) {
+            APPL_TRACE_ERROR("%s: A2D_BldAacInfo: LOCAL failed", __func__);
+        }
+        if (A2D_ParsAacInfo(&p_snk_aac_caps, (UINT8*)p_codec_cfg, FALSE) != A2D_SUCCESS) {
+            APPL_TRACE_ERROR("%s: A2D_BldAacInfo: SNK failed", __func__);
+        }
 
+        APPL_TRACE_EVENT("AAC obj_type: snk %x local %x",
+                         p_snk_aac_caps.object_type, p_local_aac_caps.object_type);
+        APPL_TRACE_EVENT("AAC samp_freq: snk %x local %x",
+                         p_snk_aac_caps.samp_freq, p_local_aac_caps.samp_freq);
+        APPL_TRACE_EVENT("AAC channels: snk %x local %x",
+                         p_snk_aac_caps.channels, p_local_aac_caps.channels);
+        APPL_TRACE_EVENT("AAC bit_rate: snk %x local %x",
+                         p_snk_aac_caps.bit_rate, p_local_aac_caps.bit_rate);
+        APPL_TRACE_EVENT("AAC vbr: snk %x local %x",
+                         p_snk_aac_caps.vbr, p_local_aac_caps.vbr);
+        return (((p_snk_aac_caps.object_type)&(p_local_aac_caps.object_type))&&
+               ((p_snk_aac_caps.samp_freq)&(p_local_aac_caps.samp_freq))&&
+               ((p_snk_aac_caps.channels)&(p_local_aac_caps.channels)));
+    }
+        break;
+#endif
+    case A2D_NON_A2DP_MEDIA_CT:
+    {
+        UINT16 codecId;
+        UINT32 vendorId;
+        UINT8* aptx_capabilities;
+
+        APPL_TRACE_DEBUG("%s aptX", __func__);
+        aptx_capabilities = &(((tBTA_AV_CO_SINK*)p_codec_cfg)->codec_caps[0]);
+        codecId = ((tA2D_APTX_CIE*)p_codec_caps)->codecId;
+        vendorId = ((tA2D_APTX_CIE*)p_codec_caps)->vendorId;
+        APPL_TRACE_DEBUG("%s codecId = %d", __func__, codecId);
+        APPL_TRACE_DEBUG("%s vendorId = %x", __func__, vendorId);
+
+        int i = 0;
+        for (i = 0 ; i < AVDT_CODEC_SIZE; i++)
+            APPL_TRACE_DEBUG("%s p_codec_cfg[%d]: %x", __func__, i,  p_codec_cfg[i]);
+
+        APPL_TRACE_EVENT("%s Caps -> sample rate/channel mode: %x configured %x", __func__, p_codec_caps[6], p_codec_cfg[9]);
+
+        if (((vendorId != ((tA2D_APTX_CIE*)(aptx_capabilities))->vendorId) || /*vendor id*/
+            (codecId !=  ((tA2D_APTX_CIE*)(aptx_capabilities))->codecId) || /*codec id*/
+            ((p_codec_caps[6] & p_codec_cfg[9]) == 0 ) /*sampling rate & channel mode*/
+           ))
+        {
+            APPL_TRACE_DEBUG("%s aptX config don't match", __func__);
+            APPL_TRACE_EVENT("%s Caps -> vendor id: %x %x %x %x", __func__, p_codec_caps[0], p_codec_caps[1], p_codec_caps[2], p_codec_caps[3]);
+            APPL_TRACE_EVENT("%s Configured: %x %x %x %x", __func__, p_codec_cfg[3], p_codec_cfg[4], p_codec_cfg[5], p_codec_cfg[6]);
+            APPL_TRACE_EVENT("%s Caps -> codec id: %x", __func__, p_codec_caps[4]);
+            APPL_TRACE_EVENT("%s Configured: %x ", __func__, p_codec_cfg[7]);
+            APPL_TRACE_EVENT("%s Caps -> Sample Rate/Channel Mode: %x Configured: %x", __func__, p_codec_caps[6], p_codec_cfg[9]);
+            return FALSE;
+        }
+        break;
+    }
     default:
         APPL_TRACE_ERROR("bta_av_co_audio_codec_cfg_matches_caps: unsupported codec id %d", codec_id);
         return FALSE;
@@ -1189,11 +1565,54 @@
  ** Returns          TRUE if the connection supports this codec, FALSE otherwise
  **
  *******************************************************************************/
-static BOOLEAN bta_av_co_audio_codec_match(const UINT8 *p_codec_caps)
+static BOOLEAN bta_av_co_audio_codec_match(const UINT8 *p_codec_caps, UINT8 codec_id)
 {
     FUNC_TRACE();
 
-    return bta_av_co_audio_codec_cfg_matches_caps(bta_av_co_cb.codec_cfg.id, p_codec_caps, bta_av_co_cb.codec_cfg.info);
+    switch(codec_id)
+    {
+      case BTIF_AV_CODEC_SBC:
+        return bta_av_co_audio_codec_cfg_matches_caps(bta_av_co_cb.codec_cfg_sbc.id, p_codec_caps, bta_av_co_cb.codec_cfg_sbc.info);
+        break;
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+      case BTIF_AV_CODEC_M24:
+        return bta_av_co_audio_codec_cfg_matches_caps(bta_av_co_cb.codec_cfg_aac.id, p_codec_caps, bta_av_co_cb.codec_cfg_aac.info);
+        break;
+#endif
+     case A2D_NON_A2DP_MEDIA_CT:
+        {
+            UINT16 codecId;
+            UINT32 vendorId;
+            int i = 0;
+            for (i = 0 ; i < AVDT_CODEC_SIZE; i++)
+                APPL_TRACE_DEBUG("%s p_codec_caps[%d]: %x", __func__, i,  p_codec_caps[i]);
+
+            codecId = ((tA2D_APTX_CIE*)p_codec_caps)->codecId;
+            vendorId = ((tA2D_APTX_CIE*)p_codec_caps)->vendorId;
+            APPL_TRACE_DEBUG("%s codecId = %d ", __func__, codecId);
+            APPL_TRACE_DEBUG("%s vendorId = %x ", __func__, vendorId);
+
+            if (codecId ==  A2D_APTX_CODEC_ID_BLUETOOTH && vendorId == A2D_APTX_VENDOR_ID) {
+                /* aptX Classic */
+                APPL_TRACE_DEBUG("%s aptX", __func__);
+                return bta_av_co_audio_codec_cfg_matches_caps(bta_av_co_cb.codec_cfg_aptx.id, p_codec_caps, bta_av_co_cb.codec_cfg_aptx.info);
+                break;
+            } else if (codecId ==  A2D_APTX_HD_CODEC_ID_BLUETOOTH && vendorId == A2D_APTX_HD_VENDOR_ID) {
+                /* aptX HD */
+                APPL_TRACE_DEBUG("%s aptX HD", __func__);
+                return bta_av_co_audio_codec_cfg_matches_caps(bta_av_co_cb.codec_cfg_aptx_hd.id, p_codec_caps, bta_av_co_cb.codec_cfg_aptx_hd.info);
+                break;
+            } else {
+                APPL_TRACE_ERROR("%s incorrect codecId (%d)", __func__, codecId);
+                APPL_TRACE_ERROR("%s incorrect vendorId (%x)", __func__, vendorId);
+                break;
+            }
+        }
+    default:
+        return bta_av_co_audio_codec_cfg_matches_caps(bta_av_co_cb.codec_cfg_sbc.id, p_codec_caps, bta_av_co_cb.codec_cfg_sbc.info);
+        break;
+    }
+    return TRUE;
 }
 
 /*******************************************************************************
@@ -1300,6 +1719,26 @@
     }
 }
 
+BOOLEAN bta_av_co_audio_is_aac_enabled(bt_bdaddr_t *remote_bdaddr)
+{
+    int retval;
+    BOOLEAN res = FALSE;
+    char is_whitelist_by_default[255] = "false";
+    retval = property_get("persist.bt.a2dp.aac_whitelist", is_whitelist_by_default, "false");
+    BTIF_TRACE_DEBUG("%s: property_get: bt.a2dp.aac_whitelist: %s, retval: %d",
+                                    __func__, is_whitelist_by_default, retval);
+
+    if (!strncmp(is_whitelist_by_default, "true", 4)) {
+        if (interop_match_addr(INTEROP_ENABLE_AAC_CODEC, remote_bdaddr))
+            res = TRUE;
+    } else if (!interop_match_addr(INTEROP_DISABLE_AAC_CODEC, remote_bdaddr)) {
+            res = TRUE;
+    }
+
+    return res;
+}
+
+
 /*******************************************************************************
  **
  ** Function         bta_av_co_audio_peer_supports_codec
@@ -1309,30 +1748,183 @@
  ** Returns          TRUE if the connection supports this codec, FALSE otherwise
  **
  *******************************************************************************/
-static BOOLEAN bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_snk_index)
+static BOOLEAN bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_snk_index, UINT8 *p_codec_type)
 {
     int index;
     UINT8 codec_type;
+    bt_bdaddr_t remote_bdaddr;
+    bdcpy(remote_bdaddr.address, p_peer->addr);
+
     FUNC_TRACE();
 
+    codec_type = bta_av_co_cb.codec_cfg->id;
+
     /* Configure the codec type to look for */
-    codec_type = bta_av_co_cb.codec_cfg.id;
+    if (p_codec_type != NULL)
+    {
+        APPL_TRACE_DEBUG("%s Incoming codec_type = %d", __func__, *p_codec_type);
+        APPL_TRACE_DEBUG("%s SEP codec_type = %d", __func__, codec_type);
+    }
+
+/* Check for aptX HD before aptX Classic as
+ * this is order of priority, if supported return true.
+ * multicast is not supported for aptX
+ */
+    if ((!bt_split_a2dp_enabled && isA2dAptXEnabled && (btif_av_is_multicast_supported() == FALSE)) ||
+        (bt_split_a2dp_enabled && (btif_av_is_codec_offload_supported(APTX)|| btif_av_is_codec_offload_supported(APTXHD))))
+    {
+        UINT16 codecId;
+        UINT32 vendorId;
+        UINT8* aptx_capabilities;
+
+        if ((bt_split_a2dp_enabled && btif_av_is_codec_offload_supported(APTXHD)) || isA2dAptXHdEnabled) {
+            for (index = 0; index < p_peer->num_sup_snks; index++)
+            {
+                if (((p_codec_type != NULL) && (p_peer->snks[index].codec_type == *p_codec_type)) ||
+                    ((p_codec_type == NULL) && (p_peer->snks[index].codec_type == A2D_NON_A2DP_MEDIA_CT)))
+                {
+                    aptx_capabilities = &(p_peer->snks[index].codec_caps[0]);
+                    codecId = ((tA2D_APTX_HD_CIE*)aptx_capabilities)->codecId;
+                    vendorId = ((tA2D_APTX_HD_CIE*)aptx_capabilities)->vendorId;
+                    int i = 0;
+                    for ( i = 0 ; i < AVDT_CODEC_SIZE; i++) {
+                        APPL_TRACE_DEBUG("%s codec_caps[%d]: %x", __func__, i, p_peer->snks[index].codec_caps[i]);
+                    }
+                    APPL_TRACE_DEBUG("%s codecId = %d", __func__, codecId);
+                    APPL_TRACE_DEBUG("%s vendorId = %x", __func__, vendorId);
+                    APPL_TRACE_DEBUG("%s p_peer->snks[index].codec_type = %x", __func__, p_peer->snks[index].codec_type );
+
+                    if (codecId ==  A2D_APTX_HD_CODEC_ID_BLUETOOTH && vendorId == A2D_APTX_HD_VENDOR_ID  )
+                    {
+                        if (p_snk_index)
+                            *p_snk_index = index;
+                        APPL_TRACE_DEBUG("%s aptX HD", __func__);
+
+                        if (bta_av_co_audio_codec_match(p_peer->snks[index].codec_caps, A2D_NON_A2DP_MEDIA_CT))
+                        {
+    #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+                            if (bta_av_co_audio_sink_has_scmst(&p_peer->snks[index]))
+    #endif
+                            {
+                                bta_av_co_cb.current_codec_id = bta_av_co_cb.codec_cfg_aptx_hd.id;
+                                bta_av_co_cb.codec_cfg = &bta_av_co_cb.codec_cfg_aptx_hd;
+                                return TRUE;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if ((bt_split_a2dp_enabled && btif_av_is_codec_offload_supported(APTX)) || isA2dAptXEnabled) {
+            for (index = 0; index < p_peer->num_sup_snks; index++)
+            {   
+                 if (((p_codec_type != NULL) && (p_peer->snks[index].codec_type == *p_codec_type)) ||
+                     ((p_codec_type == NULL) && (p_peer->snks[index].codec_type == A2D_NON_A2DP_MEDIA_CT)))
+                 {
+                     aptx_capabilities = &(p_peer->snks[index].codec_caps[0]);
+                     codecId = ((tA2D_APTX_CIE*)aptx_capabilities)->codecId;
+                     vendorId = ((tA2D_APTX_CIE*)aptx_capabilities)->vendorId;
+                     int i = 0;
+                     for ( i = 0 ; i < AVDT_CODEC_SIZE; i++) {
+                          APPL_TRACE_DEBUG("%s codec_caps[%d]: %x", __func__, i, p_peer->snks[index].codec_caps[i]);
+                     }
+                     APPL_TRACE_DEBUG("%s codecId = %d", __func__, codecId);
+                     APPL_TRACE_DEBUG("%s vendorId = %x", __func__, vendorId);
+                     APPL_TRACE_DEBUG("%s p_peer->snks[index].codec_type = %x", __func__, p_peer->snks[index].codec_type );
+
+                     if (codecId ==  A2D_APTX_CODEC_ID_BLUETOOTH && vendorId == A2D_APTX_VENDOR_ID)
+                     {
+                         if (p_snk_index)
+                             *p_snk_index = index;
+                         APPL_TRACE_DEBUG("%s aptX", __func__);
+
+                         if (bta_av_co_audio_codec_match(p_peer->snks[index].codec_caps, A2D_NON_A2DP_MEDIA_CT))
+                         {
+#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+                             if (bta_av_co_audio_sink_has_scmst(&p_peer->snks[index]))
+#endif
+                             {
+                                  bta_av_co_cb.current_codec_id = bta_av_co_cb.codec_cfg_aptx.id;
+                                  bta_av_co_cb.codec_cfg = &bta_av_co_cb.codec_cfg_aptx;
+                                  return TRUE;
+                             }
+                         }
+                     }
+                 }
+            }
+        }
+    } else
+            APPL_TRACE_DEBUG("%s aptX is disabled", __func__);
+
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    if (bt_split_a2dp_enabled && btif_av_is_codec_offload_supported(AAC) &&
+          bta_av_co_audio_is_aac_enabled(&remote_bdaddr)) {
+        for (index = 0; index < p_peer->num_sup_snks; index++)
+        {
+            APPL_TRACE_DEBUG("%s AAC: index: %d, codec_type: %d", __func__, index, p_peer->snks[index].codec_type);
+
+               if (((p_codec_type != NULL) && (p_peer->snks[index].codec_type == *p_codec_type)) ||
+                   ((p_codec_type == NULL) && (p_peer->snks[index].codec_type == bta_av_co_cb.codec_cfg_aac.id)))
+               {
+                   switch (p_peer->snks[index].codec_type)
+                   {
+                    case BTIF_AV_CODEC_M24:
+                        if (p_snk_index) *p_snk_index = index;
+                        APPL_TRACE_DEBUG("%s AAC", __func__);
+                        if (bta_av_co_audio_codec_match(p_peer->snks[index].codec_caps, BTIF_AV_CODEC_M24))
+                        {
+#if  defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+                           if (bta_av_co_audio_sink_has_scmst(&p_peer->snks[index]))
+#endif
+                            {
+                                bta_av_co_cb.current_codec_id = bta_av_co_cb.codec_cfg_aac.id;
+                                bta_av_co_cb.codec_cfg = &bta_av_co_cb.codec_cfg_aac;
+
+                                APPL_TRACE_DEBUG("%s AAC matched", __func__);
+                                return TRUE;
+                            }
+                        }
+                        break;
+
+                    default:
+                       APPL_TRACE_ERROR("AAC: bta_av_co_audio_peer_supports_codec: unsupported codec id %d", bta_av_co_cb.codec_cfg->id);
+                       //Fall thru for further SBC check
+                       break;
+                   }
+              }
+        }
+    } else
+        APPL_TRACE_DEBUG("%s AAC is disabled", __func__);
+#endif
 
 
     for (index = 0; index < p_peer->num_sup_snks; index++)
     {
-        if (p_peer->snks[index].codec_type == codec_type)
+        if (((p_codec_type != NULL) && (p_peer->snks[index].codec_type == *p_codec_type)) ||
+            ((p_codec_type == NULL) && (p_peer->snks[index].codec_type == codec_type ||
+            p_peer->snks[index].codec_type == bta_av_co_cb.codec_cfg_sbc.id)))
         {
-            switch (bta_av_co_cb.codec_cfg.id)
+            switch (p_peer->snks[index].codec_type)
             {
             case BTIF_AV_CODEC_SBC:
                 if (p_snk_index) *p_snk_index = index;
-                return bta_av_co_audio_codec_match(p_peer->snks[index].codec_caps);
+                APPL_TRACE_DEBUG("%s SBC", __func__);
+                if (bta_av_co_audio_codec_match(p_peer->snks[index].codec_caps, BTIF_AV_CODEC_SBC))
+                {
+#if  defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+                    if (bta_av_co_audio_sink_has_scmst(&p_peer->snks[index]))
+#endif
+                    {
+                        bta_av_co_cb.current_codec_id = bta_av_co_cb.codec_cfg_sbc.id;
+                        bta_av_co_cb.codec_cfg = &bta_av_co_cb.codec_cfg_sbc;
+                        return TRUE;
+                    }
+                }
                 break;
 
 
             default:
-                APPL_TRACE_ERROR("bta_av_co_audio_peer_supports_codec: unsupported codec id %d", bta_av_co_cb.codec_cfg.id);
+                APPL_TRACE_ERROR("bta_av_co_audio_peer_supports_codec: unsupported codec id %d", bta_av_co_cb.codec_cfg->id);
                 return FALSE;
                 break;
             }
@@ -1357,14 +1949,14 @@
     FUNC_TRACE();
 
     /* Configure the codec type to look for */
-    codec_type = bta_av_co_cb.codec_cfg.id;
+    codec_type = bta_av_co_cb.codec_cfg->id;
 
 
     for (index = 0; index < p_peer->num_sup_srcs; index++)
     {
         if (p_peer->srcs[index].codec_type == codec_type)
         {
-            switch (bta_av_co_cb.codec_cfg.id)
+            switch (bta_av_co_cb.codec_cfg->id)
             {
             case BTIF_AV_CODEC_SBC:
                 if (p_src_index) *p_src_index = index;
@@ -1377,7 +1969,7 @@
 
             default:
                 APPL_TRACE_ERROR("peer_src_supports_codec: unsupported codec id %d",
-                                                            bta_av_co_cb.codec_cfg.id);
+                                                            bta_av_co_cb.codec_cfg->id);
                 return FALSE;
                 break;
             }
@@ -1430,16 +2022,52 @@
 {
     FUNC_TRACE();
 
+    APPL_TRACE_DEBUG("%s codec_type = %x", __func__, codec_type);
+
+    UINT16 codecId;
+    UINT32 vendorId;
+    UINT8* aptx_capabilities;
+
     switch (codec_type)
     {
     case BTA_AV_CODEC_SBC:
         if (bta_av_sbc_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_SBC_CIE *)&bta_av_co_sbc_caps))
         {
+            APPL_TRACE_DEBUG("%s SBC ",__func__);
             return FALSE;
         }
         break;
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    case BTA_AV_CODEC_M24:
+        if (bta_av_aac_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_AAC_CIE *)&bta_av_co_aac_caps))
+        {
+            APPL_TRACE_DEBUG("%s AAC ",__func__);
+            return FALSE;
+        }
+        break;
+#endif
+    case A2D_NON_A2DP_MEDIA_CT:
+        aptx_capabilities = &(((tBTA_AV_CO_SINK*)p_codec_cfg)->codec_caps[0]);
+        codecId = ((tA2D_APTX_CIE*)(aptx_capabilities))->codecId;
+        vendorId = ((tA2D_APTX_CIE*)(aptx_capabilities))->vendorId;
+        APPL_TRACE_DEBUG("%s codecId = %d ", __func__, codecId);
+        APPL_TRACE_DEBUG("%s vendorId = %x ", __func__, vendorId);
 
-
+        if (codecId ==  A2D_APTX_HD_CODEC_ID_BLUETOOTH && vendorId == A2D_APTX_HD_VENDOR_ID) {
+            APPL_TRACE_DEBUG("%s tA2D_APTX_CIE aptX HD", __func__);
+            if (a2d_av_aptx_hd_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_APTX_HD_CIE *)&bta_av_co_aptx_hd_caps)) {
+                APPL_TRACE_DEBUG("%s aptX HD", __func__);
+                return FALSE;
+            }
+            break;
+        } else if (codecId ==  A2D_APTX_CODEC_ID_BLUETOOTH && vendorId == A2D_APTX_VENDOR_ID) {
+            APPL_TRACE_DEBUG("%s tA2D_APTX_CIE aptX", __func__);
+            if (a2d_av_aptx_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_APTX_CIE *)&bta_av_co_aptx_caps)) {
+                APPL_TRACE_DEBUG("%s aptX", __func__);
+                return FALSE;
+            }
+            break;
+        }
     default:
         APPL_TRACE_ERROR("bta_av_co_audio_media_supports_config unsupported codec type %d", codec_type);
         return FALSE;
@@ -1469,7 +2097,9 @@
 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
     BOOLEAN cp_active;
 #endif
-
+    UINT16 current_codec_id;
+    current_codec_id = bta_av_co_cb.current_codec_id;
+    UINT8 p_scb_codec_type = 0;
     FUNC_TRACE();
 
     APPL_TRACE_DEBUG("bta_av_co_audio_codec_supported");
@@ -1482,8 +2112,22 @@
         p_peer = &bta_av_co_cb.peers[index];
         if (p_peer->opened)
         {
-            if (bta_av_co_audio_peer_supports_codec(p_peer, &snk_index))
+            if (bta_av_co_audio_peer_supports_codec(p_peer, &snk_index, NULL))
             {
+                APPL_TRACE_DEBUG("%s current_codec_id: %x", __func__, bta_av_co_cb.current_codec_id);
+                p_scb_codec_type = bta_av_get_codec_type(BTA_AV_CO_AUDIO_INDX_TO_HNDL(index));
+                APPL_TRACE_DEBUG("%s p_scb_codec_type: %x", __func__, p_scb_codec_type);
+                APPL_TRACE_DEBUG("%s current_sink_index: %x", __func__, snk_index);
+                if (bta_av_co_cb.current_codec_id != p_scb_codec_type)
+                {
+                    APPL_TRACE_WARNING("%s Mismatch found in selected codec and configured codec type", __func__);
+                    if (!bta_av_co_audio_peer_supports_codec(p_peer, &snk_index, &p_scb_codec_type))
+                    {
+                        APPL_TRACE_ERROR("bta_av_co_audio_codec_supported index %d doesn't support codec", index);
+                        return FALSE;
+                    }
+                    APPL_TRACE_WARNING("%s current_sink_index changed to: %x", __func__, snk_index);
+                }
                 p_sink = &p_peer->snks[snk_index];
 
                 /* Check that this sink is compatible with the CP */
@@ -1492,7 +2136,16 @@
                     APPL_TRACE_DEBUG("bta_av_co_audio_codec_supported sink %d of peer %d doesn't support cp",
                             snk_index, index);
                     *p_status = BTIF_ERROR_SRV_AV_CP_NOT_SUPPORTED;
+#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+                    if (!bta_av_co_audio_codec_build_config(p_sink->codec_caps, codec_cfg))
+                    {
+                        APPL_TRACE_DEBUG("%s index %d doesn't support codec", __func__, index);
+                        return FALSE;
+                    }
+                    return TRUE;
+#else
                     return FALSE;
+#endif
                 }
 
                 /* Build the codec configuration for this sink */
@@ -1502,6 +2155,10 @@
                     /* Check if this sink supports SCMS */
                     cp_active = bta_av_co_audio_sink_has_scmst(p_sink);
 #endif
+                    APPL_TRACE_DEBUG("%s current_codec_id: %x", __func__, bta_av_co_cb.current_codec_id);
+                    APPL_TRACE_DEBUG("%s p_scb_codec_type: %x", __func__, p_scb_codec_type);
+                    p_scb_codec_type = bta_av_get_codec_type(BTA_AV_CO_AUDIO_INDX_TO_HNDL(index));
+                    APPL_TRACE_DEBUG("%s p_scb_codec_type: %x", __func__, p_scb_codec_type);
                     /* Check if this is a new configuration (new sink or new config) */
                     if ((p_sink != p_peer->p_snk) ||
                         (memcmp(codec_cfg, p_peer->codec_cfg, AVDT_CODEC_SIZE))
@@ -1558,12 +2215,30 @@
     FUNC_TRACE();
 
     /* Reset the current configuration to SBC */
-    bta_av_co_cb.codec_cfg.id = BTIF_AV_CODEC_SBC;
-
-    if (A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, (tA2D_SBC_CIE *)&btif_av_sbc_default_config, bta_av_co_cb.codec_cfg.info) != A2D_SUCCESS)
+    bta_av_co_cb.codec_cfg_sbc.id = BTIF_AV_CODEC_SBC;
+    if (A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, (tA2D_SBC_CIE *)&btif_av_sbc_default_config, bta_av_co_cb.codec_cfg_sbc.info) != A2D_SUCCESS)
     {
         APPL_TRACE_ERROR("bta_av_co_audio_codec_reset A2D_BldSbcInfo failed");
-    }
+    } else
+        bta_av_co_cb.codec_cfg = &(bta_av_co_cb.codec_cfg_sbc);
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    /* Reset the current configuration to AAC */
+    bta_av_co_cb.codec_cfg_aac.id = BTIF_AV_CODEC_M24;
+    if (A2D_BldAacInfo(A2D_MEDIA_TYPE_AUDIO, (tA2D_AAC_CIE *)&btif_av_aac_default_config, bta_av_co_cb.codec_cfg_aac.info) != A2D_SUCCESS)
+    {
+        APPL_TRACE_ERROR("bta_av_co_audio_codec_reset A2D_BldAacInfo failed");
+    } else
+        bta_av_co_cb.codec_cfg = &(bta_av_co_cb.codec_cfg_sbc);
+#endif
+    /* Reset the Current configuration to aptX */
+    bta_av_co_cb.codec_cfg_aptx.id = A2D_NON_A2DP_MEDIA_CT;
+    if (A2D_BldAptxInfo(A2D_MEDIA_TYPE_AUDIO, (tA2D_APTX_CIE *)&btif_av_aptx_default_config, bta_av_co_cb.codec_cfg_aptx.info) != A2D_SUCCESS)
+        APPL_TRACE_ERROR("%s A2D_BldAptxInfo failed", __func__);
+
+    /* Reset the Current configuration to aptX HD */
+    bta_av_co_cb.codec_cfg_aptx_hd.id = A2D_NON_A2DP_MEDIA_CT;
+    if (A2D_BldAptx_hdInfo(A2D_MEDIA_TYPE_AUDIO, (tA2D_APTX_HD_CIE *)&btif_av_aptx_hd_default_config, bta_av_co_cb.codec_cfg_aptx_hd.info) != A2D_SUCCESS)
+        APPL_TRACE_ERROR("%s A2D_BldAptx_hdInfo failed", __func__);
 
     mutex_global_unlock();
 }
@@ -1582,8 +2257,15 @@
 BOOLEAN bta_av_co_audio_set_codec(const tBTIF_AV_MEDIA_FEEDINGS *p_feeding, tBTIF_STATUS *p_status)
 {
     tA2D_SBC_CIE sbc_config;
-    tBTIF_AV_CODEC_INFO new_cfg;
-
+    tBTIF_AV_CODEC_INFO new_cfg_sbc;
+    tA2D_APTX_CIE aptx_config;
+    tBTIF_AV_CODEC_INFO new_cfg_aptx;
+    tA2D_APTX_HD_CIE aptx_hd_config;
+    tBTIF_AV_CODEC_INFO new_cfg_aptx_hd;
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    tA2D_AAC_CIE aac_config;
+    tBTIF_AV_CODEC_INFO new_cfg_aac;
+#endif
     FUNC_TRACE();
 
     /* Check AV feeding is supported */
@@ -1595,7 +2277,7 @@
     switch (p_feeding->format)
     {
     case BTIF_AV_CODEC_PCM:
-        new_cfg.id = BTIF_AV_CODEC_SBC;
+        new_cfg_sbc.id = BTIF_AV_CODEC_SBC;
 
         sbc_config = btif_av_sbc_default_config;
         if ((p_feeding->cfg.pcm.num_channel != 1) &&
@@ -1605,11 +2287,20 @@
             return FALSE;
         }
         if ((p_feeding->cfg.pcm.bit_per_sample != 8) &&
-            (p_feeding->cfg.pcm.bit_per_sample != 16))
+            (p_feeding->cfg.pcm.bit_per_sample != 16) &&
+            (p_feeding->cfg.pcm.bit_per_sample != 32))
         {
             APPL_TRACE_ERROR("bta_av_co_audio_set_codec PCM sample size unsupported");
             return FALSE;
         }
+        new_cfg_aptx.id = A2D_NON_A2DP_MEDIA_CT;
+        aptx_config = btif_av_aptx_default_config;
+        new_cfg_aptx_hd.id = A2D_NON_A2DP_MEDIA_CT;
+        aptx_hd_config = btif_av_aptx_hd_default_config;
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+        new_cfg_aac.id = BTIF_AV_CODEC_M24;
+        aac_config = btif_av_aac_default_config;
+#endif
         switch (p_feeding->cfg.pcm.sampling_freq)
         {
         case 8000:
@@ -1619,12 +2310,22 @@
         case 32000:
         case 48000:
             sbc_config.samp_freq = A2D_SBC_IE_SAMP_FREQ_48;
+            aptx_config.sampleRate = A2D_APTX_SAMPLERATE_48000;
+            aptx_hd_config.sampleRate = A2D_APTX_HD_SAMPLERATE_48000;
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+            aac_config.samp_freq = A2D_AAC_IE_SAMP_FREQ_48000;
+#endif
             break;
 
         case 11025:
         case 22050:
         case 44100:
             sbc_config.samp_freq = A2D_SBC_IE_SAMP_FREQ_44;
+            aptx_config.sampleRate = A2D_APTX_SAMPLERATE_44100;
+            aptx_hd_config.sampleRate = A2D_APTX_HD_SAMPLERATE_44100;
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+            aac_config.samp_freq = A2D_AAC_IE_SAMP_FREQ_44100;
+#endif
             break;
         default:
             APPL_TRACE_ERROR("bta_av_co_audio_set_codec PCM sampling frequency unsupported");
@@ -1632,11 +2333,28 @@
             break;
         }
         /* Build the codec config */
-        if (A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, &sbc_config, new_cfg.info) != A2D_SUCCESS)
+        if (A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, &sbc_config, new_cfg_sbc.info) != A2D_SUCCESS)
         {
             APPL_TRACE_ERROR("bta_av_co_audio_set_codec A2D_BldSbcInfo failed");
             return FALSE;
         }
+        if (A2D_BldAptxInfo(A2D_MEDIA_TYPE_AUDIO, &aptx_config, new_cfg_aptx.info) != A2D_SUCCESS)
+        {
+            APPL_TRACE_ERROR("%s A2D_BldAptxInfo failed", __func__);
+            return FALSE;
+        }
+        if (A2D_BldAptx_hdInfo(A2D_MEDIA_TYPE_AUDIO, &aptx_hd_config, new_cfg_aptx_hd.info) != A2D_SUCCESS)
+        {
+            APPL_TRACE_ERROR("%s A2D_BldAptx_hdInfo failed", __func__);
+            return FALSE;
+        }
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+        if (A2D_BldAacInfo(A2D_MEDIA_TYPE_AUDIO, &aac_config, new_cfg_aac.info) != A2D_SUCCESS)
+        {
+            APPL_TRACE_ERROR("%s A2D_BldAacInfo failed", __func__);
+            return FALSE;
+        }
+#endif
         break;
 
 
@@ -1646,15 +2364,164 @@
         break;
     }
 
-    /* The new config was correctly built */
-    bta_av_co_cb.codec_cfg = new_cfg;
-
+    /* The new config was correctly built. The default codec is set to be SBC */
+    bta_av_co_cb.codec_cfg_sbc = new_cfg_sbc;
+    bta_av_co_cb.codec_cfg = &bta_av_co_cb.codec_cfg_sbc;
+    bta_av_co_cb.codec_cfg_aptx= new_cfg_aptx;
+    bta_av_co_cb.codec_cfg_aptx_hd = new_cfg_aptx_hd;
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    bta_av_co_cb.codec_cfg_aac = new_cfg_aac;
+#endif
 
     /* Check all devices support it */
     *p_status = BTIF_SUCCESS;
     return bta_av_co_audio_codec_supported(p_status);
 }
 
+UINT8 bta_av_select_codec(UINT8 hdl)
+{
+    if (NULL == bta_av_co_cb.codec_cfg)
+    {
+        // Some circumstances - bta_av_co functions are called before
+        // codec clock is initialised
+        APPL_TRACE_ERROR("%s hdl = %d, no codec configured", __func__, hdl);
+        return BTIF_AV_CODEC_NONE;
+    }
+    else
+    {
+        tBTA_AV_CO_PEER *p_peer;
+        UINT8 index;
+        APPL_TRACE_ERROR("%s hdl = %d",__func__,hdl);
+        /* Retrieve the peer info */
+        p_peer = bta_av_co_get_peer(hdl);
+        /* Fix for below KW Issue
+           Pointer 'p_peer' returned from call to function 'bta_av_co_get_peer' at line
+           1993 may be NULL, will be passed to function and may be dereferenced there
+           by passing argument 1 to function 'bta_av_co_audio_peer_supports_codec' at
+           line 2001.*/
+        if (p_peer != NULL)
+        {
+            bta_av_co_audio_peer_supports_codec(p_peer,&index, NULL);
+        }
+        return bta_av_co_cb.codec_cfg->id;
+    }
+}
+
+UINT8 bta_av_co_get_current_codec()
+{
+    // Some circumstances - bta_av_co functions are called before codec clock is initialised
+    if (NULL == bta_av_co_cb.codec_cfg)
+        return BTIF_AV_CODEC_NONE;
+    else
+        return bta_av_co_cb.codec_cfg->id;
+}
+
+UINT8* bta_av_co_get_current_codecInfo()
+{
+    // We assume that the configuration block is always valid when this is called.
+    return &bta_av_co_cb.codec_cfg->info[0];
+}
+
+/*******************************************************************************
+ **
+ ** Function         bta_av_co_audio_get_codec_config
+ **
+ ** Description      Retrieves the current codec configuration.  In case of failure return
+ **                       the default SBC codec configuration.
+ **
+ ** Returns          TRUE if returned current codec config, FALSE otherwise
+ **
+ *******************************************************************************/
+BOOLEAN bta_av_co_audio_get_codec_config(UINT8 *p_config, UINT16 *p_minmtu, UINT8 type)
+{
+    BOOLEAN result = FALSE;
+    UINT8 index, jndex;
+    tBTA_AV_CO_PEER *p_peer;
+    tBTA_AV_CO_SINK *p_sink;
+    tA2D_SBC_CIE *sbc_config;
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    tA2D_AAC_CIE *aac_config;
+#endif
+
+    APPL_TRACE_EVENT("%s codec 0x%x", __func__, bta_av_co_cb.codec_cfg->id);
+
+    /* Minimum MTU is by default very large */
+    *p_minmtu = 0xFFFF;
+
+    mutex_global_lock();
+    if (type == BTIF_AV_CODEC_SBC)
+    {
+        APPL_TRACE_DEBUG("%s SBC", __func__);
+        sbc_config = (tA2D_SBC_CIE *)p_config;
+        if (A2D_ParsSbcInfo(sbc_config, bta_av_co_cb.codec_cfg_sbc.info, FALSE) == A2D_SUCCESS)
+            result = TRUE;
+        else
+            memcpy((tA2D_SBC_CIE *) p_config, &btif_av_sbc_default_config, sizeof(tA2D_SBC_CIE));
+    } else if (type == A2D_NON_A2DP_MEDIA_CT && ((tA2D_APTX_CIE *)p_config)->vendorId == A2D_APTX_VENDOR_ID && ((tA2D_APTX_CIE *)p_config)->codecId == A2D_APTX_CODEC_ID_BLUETOOTH) {
+        APPL_TRACE_DEBUG("%s aptX", __func__);
+        tA2D_APTX_CIE *aptx_config = (tA2D_APTX_CIE *)p_config;
+        if (A2D_ParsAptxInfo(aptx_config, bta_av_co_cb.codec_cfg_aptx.info, FALSE) == A2D_SUCCESS)
+            result = TRUE;
+        else
+            memcpy((tA2D_APTX_CIE *) p_config, &btif_av_aptx_default_config, sizeof(tA2D_APTX_CIE));
+    } else if (type == A2D_NON_A2DP_MEDIA_CT && ((tA2D_APTX_HD_CIE *)p_config)->vendorId == A2D_APTX_HD_VENDOR_ID && ((tA2D_APTX_HD_CIE *)p_config)->codecId == A2D_APTX_HD_CODEC_ID_BLUETOOTH) {
+        APPL_TRACE_DEBUG("%s aptX HD", __func__);
+        tA2D_APTX_HD_CIE *aptx_hd_config = (tA2D_APTX_HD_CIE *)p_config;
+        if (A2D_ParsAptx_hdInfo(aptx_hd_config, bta_av_co_cb.codec_cfg_aptx_hd.info, FALSE) == A2D_SUCCESS)
+            result = TRUE;
+        else
+            memcpy((tA2D_APTX_HD_CIE *) p_config, &btif_av_aptx_hd_default_config, sizeof(tA2D_APTX_HD_CIE));
+    } else {
+        APPL_TRACE_DEBUG("%s vendorId: %d  codecId: %d\n", __func__, ((tA2D_APTX_CIE *)p_config)->vendorId, ((tA2D_APTX_CIE *)p_config)->codecId);
+    }
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    if (type == BTIF_AV_CODEC_M24)
+    {
+        APPL_TRACE_DEBUG("%s AAC", __func__);
+        aac_config = (tA2D_AAC_CIE *)p_config;
+        if (A2D_ParsAacInfo(aac_config, bta_av_co_cb.codec_cfg_aac.info, FALSE) == A2D_SUCCESS)
+            result = TRUE;
+        else
+            memcpy((tA2D_AAC_CIE *) p_config, &btif_av_aac_default_config, sizeof(tA2D_AAC_CIE));
+    }
+#endif
+    for (index = 0; index < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); index++)
+    {
+        p_peer = &bta_av_co_cb.peers[index];
+        if (p_peer->opened)
+        {
+            if (p_peer->mtu < *p_minmtu)
+                *p_minmtu = p_peer->mtu;
+
+            for (jndex = 0; jndex < p_peer->num_sup_snks; jndex++)
+            {
+                p_sink = &p_peer->snks[jndex];
+                if (type == BTIF_AV_CODEC_SBC && p_sink->codec_type == A2D_MEDIA_CT_SBC)
+                {
+                    /* Update the bitpool boundaries of the current config */
+                    sbc_config->min_bitpool =
+                        BTA_AV_CO_MAX(p_sink->codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
+                                      sbc_config->min_bitpool);
+                    sbc_config->max_bitpool =
+                        BTA_AV_CO_MIN(p_sink->codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF],
+                                      sbc_config->max_bitpool);
+                    APPL_TRACE_EVENT("%s actual sink bitpool min %d, max %d", __func__,
+                                  sbc_config->min_bitpool, sbc_config->max_bitpool);
+                    if(sbc_config->min_bitpool > sbc_config->max_bitpool) {
+                        sbc_config->max_bitpool = sbc_config->min_bitpool;
+                        APPL_TRACE_EVENT("%s changed sink bitpool min %d, max %d", __func__,
+                                          sbc_config->min_bitpool, sbc_config->max_bitpool);
+                    }
+                    break;
+                }
+            }
+        }
+    }
+    mutex_global_unlock();
+
+    return result;
+}
+
 /*******************************************************************************
  **
  ** Function         bta_av_co_audio_get_sbc_config
@@ -1672,21 +2539,22 @@
     tBTA_AV_CO_PEER *p_peer;
     tBTA_AV_CO_SINK *p_sink;
 
-    APPL_TRACE_EVENT("bta_av_co_cb.codec_cfg.id : codec 0x%x", bta_av_co_cb.codec_cfg.id);
+    APPL_TRACE_EVENT("bta_av_co_cb.codec_cfg->id : codec 0x%x", bta_av_co_cb.codec_cfg->id);
 
     /* Minimum MTU is by default very large */
     *p_minmtu = 0xFFFF;
 
     mutex_global_lock();
-    if (bta_av_co_cb.codec_cfg.id == BTIF_AV_CODEC_SBC)
+    if (bta_av_co_cb.codec_cfg->id == BTIF_AV_CODEC_SBC)
     {
-        if (A2D_ParsSbcInfo(p_sbc_config, bta_av_co_cb.codec_cfg.info, FALSE) == A2D_SUCCESS)
+        if (A2D_ParsSbcInfo(p_sbc_config, bta_av_co_cb.codec_cfg->info, FALSE) == A2D_SUCCESS)
         {
             for (index = 0; index < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); index++)
             {
                 p_peer = &bta_av_co_cb.peers[index];
                 if (p_peer->opened)
                 {
+                    APPL_TRACE_EVENT("%s on index= %d", __func__, index);
                     if (p_peer->mtu < *p_minmtu)
                     {
                         *p_minmtu = p_peer->mtu;
@@ -1697,14 +2565,20 @@
                         if (p_sink->codec_type == A2D_MEDIA_CT_SBC)
                         {
                             /* Update the bitpool boundaries of the current config */
+                            APPL_TRACE_EVENT("%s Update the bitpool boundaries on index= %d", __func__, jndex);
                             p_sbc_config->min_bitpool =
                                BTA_AV_CO_MAX(p_sink->codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
                                              p_sbc_config->min_bitpool);
                             p_sbc_config->max_bitpool =
                                BTA_AV_CO_MIN(p_sink->codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF],
                                              p_sbc_config->max_bitpool);
-                            APPL_TRACE_EVENT("bta_av_co_audio_get_sbc_config : sink bitpool min %d, max %d",
-                                 p_sbc_config->min_bitpool, p_sbc_config->max_bitpool);
+                            APPL_TRACE_EVENT("%s: actual sink bitpool min %d, max %d", __func__,
+                                  p_sbc_config->min_bitpool, p_sbc_config->max_bitpool);
+                            if(p_sbc_config->min_bitpool > p_sbc_config->max_bitpool) {
+                                p_sbc_config->max_bitpool = p_sbc_config->min_bitpool;
+                                APPL_TRACE_EVENT("%s: updated sink bitpool min %d, max %d", __func__,
+                                                  p_sbc_config->min_bitpool, p_sbc_config->max_bitpool);
+                            }
                             break;
                         }
                     }
@@ -1717,12 +2591,67 @@
     if (!result)
     {
         /* Not SBC, still return the default values */
+        APPL_TRACE_EVENT("%s Not SBC, still return the default values", __func__);
         *p_sbc_config = btif_av_sbc_default_config;
     }
     mutex_global_unlock();
 
     return result;
 }
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+/*******************************************************************************
+ **
+ ** Function         bta_av_co_audio_get_aac_config
+ **
+ ** Description      Retrieves the AAC codec configuration.  If the codec in use
+ **                  is not AAC, return the default AAC codec configuration.
+ **
+ ** Returns          TRUE if codec is AAC, FALSE otherwise
+ **
+ *******************************************************************************/
+BOOLEAN bta_av_co_audio_get_aac_config(tA2D_AAC_CIE *p_aac_config, UINT16 *p_minmtu)
+{
+    BOOLEAN result = FALSE;
+    UINT8 index;
+    tBTA_AV_CO_PEER *p_peer;
+
+    APPL_TRACE_EVENT("bta_av_co_cb.codec_cfg->id : codec 0x%x", bta_av_co_cb.codec_cfg->id);
+
+    /* Minimum MTU is by default very large */
+    *p_minmtu = 0xFFFF;
+
+    mutex_global_lock();
+    if (bta_av_co_cb.codec_cfg->id == BTIF_AV_CODEC_M24)
+    {
+        if (A2D_ParsAacInfo(p_aac_config, bta_av_co_cb.codec_cfg->info, FALSE) == A2D_SUCCESS)
+        {
+            for (index = 0; index < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); index++)
+            {
+                p_peer = &bta_av_co_cb.peers[index];
+                if (p_peer->opened)
+                {
+                    APPL_TRACE_EVENT("%s on index= %d", __func__, index);
+                    if (p_peer->mtu < *p_minmtu)
+                    {
+                        *p_minmtu = p_peer->mtu;
+                    }
+                }
+            }
+            result = TRUE;
+        }
+    }
+
+    if (!result)
+    {
+        /* Not AAC, still return the default values */
+        APPL_TRACE_EVENT("%s Not SBC, still return the default values", __func__);
+        *p_aac_config = btif_av_aac_default_config;
+    }
+    mutex_global_unlock();
+
+    return result;
+}
+#endif
 
 /*******************************************************************************
  **
@@ -1767,7 +2696,7 @@
     /* Reset the control block */
     memset(&bta_av_co_cb, 0, sizeof(bta_av_co_cb));
 
-    bta_av_co_cb.codec_cfg_setconfig.id = BTIF_AV_CODEC_NONE;
+    bta_av_co_cb.codec_cfg_setconfig = NULL;
 
 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
     bta_av_co_cp_set_flag(BTA_AV_CP_SCMS_COPY_NEVER);
@@ -1833,11 +2762,41 @@
 BOOLEAN bta_av_co_get_remote_bitpool_pref(UINT8 *min, UINT8 *max)
 {
     /* check if remote peer did a set config */
-    if (bta_av_co_cb.codec_cfg_setconfig.id == BTIF_AV_CODEC_NONE)
+    if (bta_av_co_cb.codec_cfg_setconfig == NULL)
         return FALSE;
 
-    *min = bta_av_co_cb.codec_cfg_setconfig.info[BTA_AV_CO_SBC_MIN_BITPOOL_OFF];
-    *max = bta_av_co_cb.codec_cfg_setconfig.info[BTA_AV_CO_SBC_MAX_BITPOOL_OFF];
+    *min = bta_av_co_cb.codec_cfg_setconfig->info[BTA_AV_CO_SBC_MIN_BITPOOL_OFF];
+    *max = bta_av_co_cb.codec_cfg_setconfig->info[BTA_AV_CO_SBC_MAX_BITPOOL_OFF];
 
     return TRUE;
 }
+
+/*******************************************************************************
+**
+** Function         bta_av_co_audio_is_offload_supported
+**
+** Description      This function is called by AV to check if DUT is in offload
+**                  mode.
+**
+** Returns          TRUE if offload is enabled, FALSE otherwise
+**
+*******************************************************************************/
+BOOLEAN bta_av_co_audio_is_offload_supported(void)
+{
+    return btif_av_is_offload_supported();
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_co_audio_is_codec_supported
+**
+** Description      This function is called by AV to check if corresponding
+**                  codec is supported in offload mode.
+**
+** Returns          TRUE if codec is supported in offload, FALSE otherwise
+**
+*******************************************************************************/
+BOOLEAN bta_av_co_audio_is_codec_supported(int codec)
+{
+    return btif_av_is_codec_offload_supported(codec);
+}
diff --git a/btif/co/bta_dm_co.c b/btif/co/bta_dm_co.c
index 55b2f86..5c3b0a3 100644
--- a/btif/co/bta_dm_co.c
+++ b/btif/co/bta_dm_co.c
@@ -30,6 +30,11 @@
 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
 #include "bte_appl.h"
 
+#if (defined BTM_NO_MITM_NO_BONDING_INCLUDED && BTM_NO_MITM_NO_BONDING_INCLUDED == TRUE)
+tBTE_APPL_CFG bte_appl_cfg = { 0x0, 0x4, 0x0, 0x0, 0x10 };
+#elif (defined BTM_NO_MITM_INCLUDED && BTM_NO_MITM_INCLUDED == TRUE)
+tBTE_APPL_CFG bte_appl_cfg = { 0x1, 0x4, 0x7, 0x7, 0x10 };
+#else
 tBTE_APPL_CFG bte_appl_cfg =
 {
 #if SMP_INCLUDED == TRUE
@@ -43,6 +48,7 @@
     BTM_BLE_MAX_KEY_SIZE
 };
 #endif
+#endif
 
 /*******************************************************************************
 **
diff --git a/btif/co/bta_hh_co.c b/btif/co/bta_hh_co.c
index c95a19d..344f4ac 100644
--- a/btif/co/bta_hh_co.c
+++ b/btif/co/bta_hh_co.c
@@ -35,6 +35,8 @@
 #include "bta_hh_co.h"
 #include "btif_hh.h"
 #include "btif_util.h"
+#include "btcore/include/bdaddr.h"
+#include "device/include/interop.h"
 
 const char *dev_path = "/dev/uhid";
 
@@ -44,6 +46,94 @@
 static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX];
 #endif
 
+#define REPORT_DESC_REPORT_ID           0x05
+#define REPORT_DESC_DIGITIZER_PAGE      0x0D
+#define REPORT_DESC_START_COLLECTION    0xA1
+#define REPORT_DESC_END_COLLECTION      0xC0
+
+static void remove_digitizer_descriptor(UINT8 **data, UINT16 *length)
+{
+    UINT8 *startDescPtr = *data;
+    UINT8 *desc = *data;
+
+    /* Parse until complete report descriptor is parsed */
+    while (startDescPtr < *data + *length)
+    {
+        UINT8 item = *startDescPtr++;
+        UINT8 usage_page;
+
+        switch (item) {
+            case REPORT_DESC_REPORT_ID: // Report ID
+                usage_page = *startDescPtr;
+                if (usage_page == REPORT_DESC_DIGITIZER_PAGE)
+                {
+                    // digitizer usage page
+                    UINT8 *traversePtr = startDescPtr;
+                    UINT8 num_of_collections = 0;
+                    UINT8 num_of_end_collections = 0;
+                    UINT16 remainingBytesToBeCopied = 0;
+                    /* increment pointer until digitizer descriptor is parsed
+                     * completely or start collection matches end collection */
+                    while ((num_of_collections == 0 || (num_of_collections !=
+                        num_of_end_collections)) && (traversePtr <
+                        *data + *length))
+                    {
+                        if (*traversePtr == REPORT_DESC_START_COLLECTION) {
+                            /* Increment number of collections for
+                             * digitizer descriptor */
+                            num_of_collections++;
+                        }
+                        if (*traversePtr == REPORT_DESC_END_COLLECTION) {
+                            /* Increment number of end collections for
+                             * digitizer descriptor */
+                            num_of_end_collections++;
+                        }
+                        /* increment the pointer to continue parsing
+                         * the digitizer descriptor */
+                        UNUSED(*traversePtr++);
+                    }
+                    remainingBytesToBeCopied = *length - (traversePtr - *data);
+                    BTIF_TRACE_DEBUG("starting point of digitizer desc = %d\n",
+                        (startDescPtr - *data) - 1);
+                    BTIF_TRACE_DEBUG("start collection = %d, end collection = "
+                        " %d\n", num_of_collections, num_of_end_collections);
+                    BTIF_TRACE_DEBUG("end point of digitizer desc = %d\n",
+                        (traversePtr - *data));
+                    BTIF_TRACE_DEBUG("length of digitizer desc = %d\n",
+                        traversePtr - startDescPtr + 2);
+                    BTIF_TRACE_DEBUG("bytes remaining to be copied = %d\n",
+                        remainingBytesToBeCopied);
+                    if (remainingBytesToBeCopied)
+                    {
+                        UINT32 i;
+                        UINT8 *newDescPtr = traversePtr;
+                        UINT32 digDescStartPoint = (startDescPtr - *data) - 1;
+                        UINT32 digDescEndPoint = *length -
+                            (traversePtr - startDescPtr) - 1;
+                        /* copy the remaining bytes in descriptor to the
+                         * existing place of digitizer descriptor */
+                        for (i = digDescStartPoint; i < digDescEndPoint; i ++) {
+                            desc[i] = *newDescPtr++;
+                        }
+                    }
+                    /* update the length as digitizer descriptor is removed */
+                    *length = *length - (traversePtr - startDescPtr) - 1;
+                    BTIF_TRACE_DEBUG("new length of report desc = %d\n",
+                        *length);
+                    /* Update the start descriptor again to continue parsing
+                     * for digitizer records assuming more than 1 digitizer
+                     * record exists in report descriptor */
+                    startDescPtr --;
+                }
+                break;
+
+            default:
+                startDescPtr += (item & 0x03);
+                break;
+        }
+    }
+}
+
 void uhid_set_non_blocking(int fd)
 {
     int opts = fcntl(fd, F_GETFL);
@@ -56,6 +146,19 @@
         APPL_TRACE_EVENT("%s() Setting non-blocking flag failed (%s)", __func__, strerror(errno));
 }
 
+static void lst_free_cb (void * rpt_id)
+{
+    UINT32 *p_rpt_id = (UINT32 *)rpt_id;
+
+    if (rpt_id == NULL)
+    return;
+
+    APPL_TRACE_DEBUG("%s: freeing report id %d",
+        __func__, (int)*p_rpt_id);
+    free(rpt_id);
+    rpt_id = NULL;
+}
+
 /*Internal function to perform UHID write and error checking*/
 static int uhid_write(int fd, const struct uhid_event *ev)
 {
@@ -84,15 +187,24 @@
     struct uhid_event ev;
     memset(&ev, 0, sizeof(ev));
 
+    if(!p_dev)
+    {
+        APPL_TRACE_ERROR("%s: Device not found", __func__)
+        return -1;
+    }
+
     ssize_t ret;
+
+    APPL_TRACE_DEBUG("%s: reading", __func__);
     OSI_NO_INTR(ret = read(p_dev->fd, &ev, sizeof(ev)));
+    APPL_TRACE_DEBUG("%s: read %d bytes", __func__, ret);
 
     if (ret == 0) {
-        APPL_TRACE_ERROR("%s: Read HUP on uhid-cdev %s", __FUNCTION__,
+        APPL_TRACE_ERROR("%s: Read HUP on uhid-cdev %s", __func__,
                                                  strerror(errno));
         return -EFAULT;
     } else if (ret < 0) {
-        APPL_TRACE_ERROR("%s: Cannot read uhid-cdev: %s", __FUNCTION__,
+        APPL_TRACE_ERROR("%s: Cannot read uhid-cdev: %s", __func__,
                                                 strerror(errno));
         return -errno;
     } else if ((ev.type == UHID_OUTPUT) || (ev.type==UHID_OUTPUT_EV)) {
@@ -100,11 +212,12 @@
         // ensure we read full event descriptor
         if (ret < (ssize_t)sizeof(ev)) {
             APPL_TRACE_ERROR("%s: Invalid size read from uhid-dev: %ld != %lu",
-                         __FUNCTION__, ret, sizeof(ev.type));
+                         __func__, ret, sizeof(ev.type));
             return -EFAULT;
         }
     }
 
+    APPL_TRACE_DEBUG("%s: received event = %d", __func__, ev.type);
     switch (ev.type) {
     case UHID_START:
         APPL_TRACE_DEBUG("UHID_START from uhid-dev\n");
@@ -125,7 +238,7 @@
     case UHID_OUTPUT:
         if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.output))) {
             APPL_TRACE_ERROR("%s: Invalid size read from uhid-dev: %zd < %zu",
-                             __FUNCTION__, ret,
+                             __func__, ret,
                              sizeof(ev.type) + sizeof(ev.u.output));
             return -EFAULT;
         }
@@ -137,20 +250,81 @@
             btif_hh_setreport(p_dev, BTHH_FEATURE_REPORT,
                               ev.u.output.size, ev.u.output.data);
         else if(ev.u.output.rtype == UHID_OUTPUT_REPORT)
+        {
+            if (ev.u.output.size == BTIF_HH_OUTPUT_REPORT_SIZE &&
+                !memcmp(&p_dev->last_output_rpt_data, &ev.u.output.data,
+                BTIF_HH_OUTPUT_REPORT_SIZE)) {
+                /* Last output report same as current output report, don't inform to remote
+                 * device as this could be the case when reports are being sent due to
+                 * device suspend/resume. If same output report is sent to remote device
+                 * device which uses UART as transport might not be able to suspend at all
+                 * leading to higher battery drain.
+                 */
+                APPL_TRACE_VERBOSE("UHID_OUTPUT: data same returning");
+                return 0;
+            }
+            /* Copy new output report data for future tracking */
+            memcpy(&p_dev->last_output_rpt_data, &ev.u.output.data, ev.u.output.size);
             btif_hh_setreport(p_dev, BTHH_OUTPUT_REPORT,
                               ev.u.output.size, ev.u.output.data);
+        }
         else
             btif_hh_setreport(p_dev, BTHH_INPUT_REPORT,
                               ev.u.output.size, ev.u.output.data);
-           break;
+        break;
     case UHID_OUTPUT_EV:
         APPL_TRACE_DEBUG("UHID_OUTPUT_EV from uhid-dev\n");
         break;
-    case UHID_FEATURE:
-        APPL_TRACE_DEBUG("UHID_FEATURE from uhid-dev\n");
+    case UHID_SET_REPORT:
+        if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.set_report))) {
+            APPL_TRACE_ERROR("%s: UHID_SET_REPORT: Invalid size read from "
+                "uhid-dev: %zd < %zu", __func__, ret,
+                sizeof(ev.type) + sizeof(ev.u.set_report));
+            return -EFAULT;
+        }
+        APPL_TRACE_DEBUG("UHID_SET_REPORT: Report type = %d, report_size = %d"
+                            ,ev.u.set_report.rtype, ev.u.set_report.size);
+        UINT32 *p_set_rpt_id = (UINT32 *)malloc(sizeof(UINT32));
+        if (!p_set_rpt_id) {
+          APPL_TRACE_ERROR("%s unable to allocate p_set_rpt_id", __func__);
+          return -ENOMEM;
+        }
+        *p_set_rpt_id = ev.u.set_report.id;
+        if (p_dev->set_rpt_id_list) {
+            if (!list_append(p_dev->set_rpt_id_list, (void *)p_set_rpt_id)) {
+                APPL_TRACE_ERROR("%s: list_append failed", __func__)
+                return -EFAULT;
+            }
+        }
+        if (ev.u.set_report.rtype == UHID_FEATURE_REPORT)
+            btif_hh_setreport(p_dev, BTHH_FEATURE_REPORT,
+                              ev.u.set_report.size, ev.u.set_report.data);
+        else if (ev.u.set_report.rtype == UHID_OUTPUT_REPORT)
+            btif_hh_setreport(p_dev, BTHH_OUTPUT_REPORT,
+                              ev.u.set_report.size, ev.u.set_report.data);
+        else
+            btif_hh_setreport(p_dev, BTHH_INPUT_REPORT,
+                              ev.u.set_report.size, ev.u.set_report.data);
         break;
-    case UHID_FEATURE_ANSWER:
-        APPL_TRACE_DEBUG("UHID_FEATURE_ANSWER from uhid-dev\n");
+    case UHID_GET_REPORT:
+        if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.get_report))) {
+            APPL_TRACE_ERROR("%s: UHID_GET_REPORT: Invalid size read from "
+                "uhid-dev: %zd < %zu", __func__, ret,
+                sizeof(ev.type) + sizeof(ev.u.get_report));
+            return -EFAULT;
+        }
+        APPL_TRACE_DEBUG("UHID_GET_REPORT: Report type = %d",
+            ev.u.get_report.rtype);
+        p_dev->get_rpt_snt++;
+        if (ev.u.get_report.rtype == UHID_FEATURE_REPORT)
+            btif_hh_getreport(p_dev, BTHH_FEATURE_REPORT,
+                              ev.u.get_report.rnum, 0);
+        else if (ev.u.get_report.rtype == UHID_OUTPUT_REPORT)
+            btif_hh_getreport(p_dev, BTHH_OUTPUT_REPORT,
+                              ev.u.get_report.rnum, 0);
+        else
+            btif_hh_getreport(p_dev, BTHH_INPUT_REPORT,
+                              ev.u.get_report.rnum, 0);
         break;
 
     default:
@@ -282,7 +456,7 @@
 
     if (dev_handle == BTA_HH_INVALID_HANDLE) {
         APPL_TRACE_WARNING("%s: Oops, dev_handle (%d) is invalid...",
-                           __FUNCTION__, dev_handle);
+                           __func__, dev_handle);
         return;
     }
 
@@ -292,22 +466,22 @@
             p_dev->dev_handle == dev_handle) {
             // We found a device with the same handle. Must be a device reconnected.
             APPL_TRACE_WARNING("%s: Found an existing device with the same handle "
-                                                                "dev_status = %d",__FUNCTION__,
+                                                                "dev_status = %d",__func__,
                                                                 p_dev->dev_status);
-            APPL_TRACE_WARNING("%s:     bd_addr = [%02X:%02X:%02X:%02X:%02X:]", __FUNCTION__,
+            APPL_TRACE_WARNING("%s:     bd_addr = [%02X:%02X:%02X:%02X:%02X:]", __func__,
                  p_dev->bd_addr.address[0], p_dev->bd_addr.address[1], p_dev->bd_addr.address[2],
                  p_dev->bd_addr.address[3], p_dev->bd_addr.address[4]);
                  APPL_TRACE_WARNING("%s:     attr_mask = 0x%04x, sub_class = 0x%02x, app_id = %d",
-                                  __FUNCTION__, p_dev->attr_mask, p_dev->sub_class, p_dev->app_id);
+                                  __func__, p_dev->attr_mask, p_dev->sub_class, p_dev->app_id);
 
             if(p_dev->fd<0) {
                 p_dev->fd = open(dev_path, O_RDWR | O_CLOEXEC);
                 if (p_dev->fd < 0){
                     APPL_TRACE_ERROR("%s: Error: failed to open uhid, err:%s",
-                                                                    __FUNCTION__,strerror(errno));
+                                                                    __func__,strerror(errno));
                     return;
                 }else
-                    APPL_TRACE_DEBUG("%s: uhid fd = %d", __FUNCTION__, p_dev->fd);
+                    APPL_TRACE_DEBUG("%s: uhid fd = %d", __func__, p_dev->fd);
             }
 
             p_dev->hh_keep_polling = 1;
@@ -333,10 +507,10 @@
                 p_dev->fd = open(dev_path, O_RDWR | O_CLOEXEC);
                 if (p_dev->fd < 0){
                     APPL_TRACE_ERROR("%s: Error: failed to open uhid, err:%s",
-                                                                    __FUNCTION__,strerror(errno));
+                                                                    __func__,strerror(errno));
                     return;
                 }else{
-                    APPL_TRACE_DEBUG("%s: uhid fd = %d", __FUNCTION__, p_dev->fd);
+                    APPL_TRACE_DEBUG("%s: uhid fd = %d", __func__, p_dev->fd);
                     p_dev->hh_keep_polling = 1;
                     p_dev->hh_poll_thread_id = create_thread(btif_hh_poll_event_thread, p_dev);
                 }
@@ -348,12 +522,18 @@
     }
 
     if (p_dev == NULL) {
-        APPL_TRACE_ERROR("%s: Error: too many HID devices are connected", __FUNCTION__);
+        APPL_TRACE_ERROR("%s: Error: too many HID devices are connected", __func__);
         return;
     }
 
     p_dev->dev_status = BTHH_CONN_STATE_CONNECTED;
-    APPL_TRACE_DEBUG("%s: Return device status %d", __FUNCTION__, p_dev->dev_status);
+    APPL_TRACE_DEBUG("%s: allocating the set_rpt_id_list", __func__);
+    memset(&p_dev->last_output_rpt_data, 0, BTIF_HH_OUTPUT_REPORT_SIZE);
+    p_dev->set_rpt_id_list = list_new(lst_free_cb);
+    if (!p_dev->set_rpt_id_list) {
+        APPL_TRACE_ERROR("%s: unable to create list", __func__);
+    }
+    APPL_TRACE_DEBUG("%s: Return device status %d", __func__, p_dev->dev_status);
 }
 
 
@@ -374,19 +554,25 @@
     UINT32 i;
     btif_hh_device_t *p_dev = NULL;
 
-    APPL_TRACE_WARNING("%s: dev_handle = %d, app_id = %d", __FUNCTION__, dev_handle, app_id);
+    APPL_TRACE_WARNING("%s: dev_handle = %d, app_id = %d", __func__, dev_handle, app_id);
     if (dev_handle == BTA_HH_INVALID_HANDLE) {
-        APPL_TRACE_WARNING("%s: Oops, dev_handle (%d) is invalid...", __FUNCTION__, dev_handle);
+        APPL_TRACE_WARNING("%s: Oops, dev_handle (%d) is invalid...", __func__, dev_handle);
         return;
     }
 
     for (i = 0; i < BTIF_HH_MAX_HID; i++) {
         p_dev = &btif_hh_cb.devices[i];
+        if (p_dev->set_rpt_id_list && list_length(p_dev->set_rpt_id_list)) {
+            APPL_TRACE_DEBUG("%s: freeing the set_rpt_id_list", __func__);
+            list_free(p_dev->set_rpt_id_list);
+            p_dev->set_rpt_id_list = NULL;
+        }
         if (p_dev->dev_status != BTHH_CONN_STATE_UNKNOWN && p_dev->dev_handle == dev_handle) {
             APPL_TRACE_WARNING("%s: Found an existing device with the same handle "
                                                         "dev_status = %d, dev_handle =%d"
-                                                        ,__FUNCTION__,p_dev->dev_status
+                                                        ,__func__,p_dev->dev_status
                                                         ,p_dev->dev_handle);
+            memset(&p_dev->last_output_rpt_data, 0, BTIF_HH_OUTPUT_REPORT_SIZE);
             btif_hh_close_poll_thread(p_dev);
             break;
         }
@@ -435,7 +621,6 @@
     }
 }
 
-
 /*******************************************************************************
 **
 ** Function         bta_hh_co_send_hid_info
@@ -467,6 +652,11 @@
                                                                     vendor_id, product_id,
                                                                     version, ctry_code);
 
+    if (interop_match_vendor_product_ids(INTEROP_REMOVE_HID_DIG_DESCRIPTOR,
+        vendor_id, product_id) ||
+        interop_match_name(INTEROP_REMOVE_HID_DIG_DESCRIPTOR, dev_name))
+        remove_digitizer_descriptor(&p_dscp, (UINT16 *)&dscp_len);
+
     //Create and send hid descriptor to kernel
     memset(&ev, 0, sizeof(ev));
     ev.type = UHID_CREATE;
@@ -483,7 +673,11 @@
     ev.u.create.product = product_id;
     ev.u.create.version = version;
     ev.u.create.country = ctry_code;
+    // block write to uhid driver until create completes
+    p_dev->ready_for_data = FALSE;
     result = uhid_write(p_dev->fd, &ev);
+    // unblock write to uhid driver now
+    p_dev->ready_for_data = TRUE;
 
     APPL_TRACE_WARNING("%s: wrote descriptor to fd = %d, dscp_len = %d, result = %d", __FUNCTION__,
                                                                     p_dev->fd, dscp_len, result);
@@ -497,6 +691,90 @@
     }
 }
 
+/*******************************************************************************
+**
+** Function         bta_hh_co_set_rpt_rsp
+**
+** Description      This callout function is executed by HH when Set Report Response is received
+**                      on Control Channel.
+**
+** Returns          void.
+**
+*******************************************************************************/
+void bta_hh_co_set_rpt_rsp(UINT8 dev_handle, UINT8 status)
+{
+    struct uhid_event ev;
+    btif_hh_device_t *p_dev;
+
+    APPL_TRACE_VERBOSE("%s: dev_handle = %d", __func__, dev_handle);
+
+    p_dev = btif_hh_find_connected_dev_by_handle(dev_handle);
+    if (p_dev == NULL) {
+        APPL_TRACE_WARNING("%s: Error: unknown HID device handle %d", __func__, dev_handle);
+        return;
+    }
+    // Send the HID report to the kernel.
+    if (p_dev->fd >= 0 && p_dev->set_rpt_id_list &&
+        list_length(p_dev->set_rpt_id_list)) {
+        memset(&ev, 0, sizeof(ev));
+        ev.type = UHID_SET_REPORT_REPLY;
+        /* get the report id from start of list */
+        UINT32 *set_report_reply_id = list_front(p_dev->set_rpt_id_list);
+        if (set_report_reply_id) {
+            ev.u.set_report_reply.id = *set_report_reply_id;
+            APPL_TRACE_VERBOSE("%s: set_report_reply_id = %d",
+                __func__, *(set_report_reply_id));
+            /* remove the entry from list now */
+            if (!list_remove(p_dev->set_rpt_id_list, set_report_reply_id)) {
+                APPL_TRACE_ERROR("%s: unable to remove set_report_reply_id = %d",
+                    __func__, *(set_report_reply_id));
+            }
+        }
+        ev.u.set_report_reply.err = status;
+        uhid_write(p_dev->fd, &ev);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_co_get_rpt_rsp
+**
+** Description      This callout function is executed by HH when Get Report Response is received
+**                      on Control Channel.
+**
+** Returns          void.
+**
+*******************************************************************************/
+void bta_hh_co_get_rpt_rsp(UINT8 dev_handle, UINT8 status, UINT8 *p_rpt, UINT16 len)
+{
+    struct uhid_event ev;
+    btif_hh_device_t *p_dev;
+
+    APPL_TRACE_VERBOSE("%s: dev_handle = %d", __func__, dev_handle);
+
+    p_dev = btif_hh_find_connected_dev_by_handle(dev_handle);
+    if (p_dev == NULL) {
+        APPL_TRACE_WARNING("%s: Error: unknown HID device handle %d", __func__, dev_handle);
+        return;
+    }
+    // Send the HID report to the kernel.
+    if (p_dev->fd >= 0 && p_dev->get_rpt_snt--) {
+        memset(&ev, 0, sizeof(ev));
+        ev.type = UHID_GET_REPORT_REPLY;
+        ev.u.get_report_reply.err = status;
+        ev.u.get_report_reply.size = len;
+        if (len > 0) {
+            if (len > UHID_DATA_MAX) {
+                APPL_TRACE_WARNING("%s: Report size greater than allowed size",
+                                   __func__);
+                return;
+            }
+            memcpy(ev.u.get_report_reply.data, p_rpt, len);
+        }
+        uhid_write(p_dev->fd, &ev);
+    }
+}
+
 #if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE)
 /*******************************************************************************
 **
@@ -568,7 +846,7 @@
         remote_bda[3], remote_bda[4], remote_bda[5]);
 
     size_t len = btif_config_get_bin_length(bdstr, "HidReport");
-    if (!p_num_rpt && len < sizeof(tBTA_HH_RPT_CACHE_ENTRY))
+    if (!p_num_rpt || len < sizeof(tBTA_HH_RPT_CACHE_ENTRY))
         return NULL;
 
     if (len > sizeof(sReportCache))
diff --git a/btif/co/bta_hl_co.c b/btif/co/bta_hl_co.c
index e76d078..fbfb7df 100644
--- a/btif/co/bta_hl_co.c
+++ b/btif/co/bta_hl_co.c
@@ -332,7 +332,7 @@
     {
         p_dcb = BTIF_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
 
-        if (p_dcb->tx_size <= buf_size )
+        if ((p_dcb->tx_size <= buf_size) && p_dcb->p_tx_pkt)
         {
             memcpy(p_buf, p_dcb->p_tx_pkt, p_dcb->tx_size);
             osi_free_and_reset((void **)&p_dcb->p_tx_pkt);
@@ -341,7 +341,7 @@
         }
     }
 
-
+    BTIF_TRACE_WARNING("%s status = %d ", __FUNCTION__, status);
     bta_hl_ci_get_tx_data(mdl_handle,  status, evt);
 
 }
diff --git a/btif/include/btif_api.h b/btif/include/btif_api.h
index 355f188..14e16cb 100644
--- a/btif/include/btif_api.h
+++ b/btif/include/btif_api.h
@@ -379,6 +379,17 @@
 
 /*******************************************************************************
 **
+** Function         btif_hci_cmd_send
+**
+** Description      Sends a HCI Raw command to the controller
+**
+** Returns          BT_STATUS_SUCCESS on success
+**
+*******************************************************************************/
+bt_status_t btif_hci_cmd_send(uint16_t opcode, uint8_t *buf, uint8_t len);
+
+/*******************************************************************************
+**
 ** Function         btif_le_test_mode
 **
 ** Description     Sends a HCI BLE Test command to the Controller
diff --git a/btif/include/btif_av.h b/btif/include/btif_av.h
index 1fc7cfe..8e2de02 100644
--- a/btif/include/btif_av.h
+++ b/btif/include/btif_av.h
@@ -32,6 +32,7 @@
 #include "btif_sm.h"
 #include "bta_av_api.h"
 
+#define BTIF_RC_HANDLE_NONE 0xFF
 
 /*******************************************************************************
 **  Type definitions for callback functions
@@ -48,6 +49,11 @@
     BTIF_AV_OFFLOAD_START_REQ_EVT,
     BTIF_AV_SINK_FOCUS_REQ_EVT,
     BTIF_AV_CLEANUP_REQ_EVT,
+    BTIF_AV_UPDATE_ENCODER_REQ_EVT,
+    BTIF_AV_REMOTE_SUSPEND_STREAM_REQ_EVT,
+    BTIF_AV_RESET_REMOTE_STARTED_FLAG_EVT,
+    BTIF_AV_RESET_REMOTE_STARTED_FLAG_UPDATE_AUDIO_STATE_EVT,
+    BTIF_AV_INIT_REQ_EVT,
 } btif_av_sm_event_t;
 
 
@@ -77,7 +83,7 @@
 **
 *******************************************************************************/
 
-bt_bdaddr_t btif_av_get_addr(void);
+bt_bdaddr_t btif_av_get_addr(BD_ADDR address);
 
 /*******************************************************************************
 ** Function         btif_av_is_sink_enabled
@@ -204,6 +210,18 @@
 
 /*******************************************************************************
 **
+** Function         btif_av_any_br_peer
+**
+** Description      Check if the any of connected devices is BR device.
+**
+** Returns          TRUE if connected to any BR device, FALSE otherwise.
+**
+*******************************************************************************/
+
+BOOLEAN btif_av_any_br_peer(void);
+
+/*******************************************************************************
+**
 ** Function         btif_av_peer_supports_3mbps
 **
 ** Description      Check if the connected A2DP device supports
@@ -215,4 +233,74 @@
 *******************************************************************************/
 BOOLEAN btif_av_peer_supports_3mbps(void);
 
+/*******************************************************************************
+**
+** Function         btif_av_check_flag_remote_suspend
+**
+** Description      Check whether remote suspend flag is set or not
+**
+** Returns          TRUE if remote suspen flag set
+**
+*******************************************************************************/
+BOOLEAN btif_av_check_flag_remote_suspend(int index);
+
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+/******************************************************************************
+**
+** Function         btif_av_get_streaming_channel_id
+**
+** Description      Returns streaming channel id
+**
+** Returns          channel id
+********************************************************************************/
+UINT16 btif_av_get_streaming_channel_id(void);
+
+/******************************************************************************
+**
+** Function         btif_av_get_peer_addr
+**
+** Description     Returns peer device address
+**
+** Returns          peer address
+********************************************************************************/
+void btif_av_get_peer_addr(bt_bdaddr_t *peer_bda);
+
+/*******************************************************************************
+**
+** Function         btif_av_get_current_playing_dev_idx
+**
+** Description      Returns the current playing device index.
+**
+** Returns          index.
+**
+*******************************************************************************/
+int btif_av_get_current_playing_dev_idx();
+#else
+#define btif_av_get_streaming_channel_id() (0)
+#define btif_av_get_peer_addr(peer_bda) (0)
+#define btif_av_get_current_playing_dev_idx() (0)
+#endif
+
+/*******************************************************************************
+**
+** Function         btif_av_get_multicast_state
+**
+** Description      Check if A2DP multicast is enabled
+**
+** Returns          TRUE if a2dp multicast is enabled
+**
+*******************************************************************************/
+BOOLEAN btif_av_get_multicast_state();
+
+/*******************************************************************************
+**
+** Function         btif_av_is_multicast_supported
+**
+** Description      Check if A2DP multicast is supported
+**
+** Returns          TRUE if a2dp multicast is supported
+**
+*******************************************************************************/
+BOOLEAN btif_av_is_multicast_supported();
+
 #endif /* BTIF_AV_H */
diff --git a/btif/include/btif_av_api.h b/btif/include/btif_av_api.h
index 86cd40b..857fed2 100644
--- a/btif/include/btif_av_api.h
+++ b/btif/include/btif_av_api.h
@@ -1,4 +1,10 @@
 /******************************************************************************
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a contribution.
+ ******************************************************************************/
+
+/******************************************************************************
  *
  *  Copyright (C) 2009-2012 Broadcom Corporation
  *
@@ -43,9 +49,9 @@
  *****************************************************************************/
 
 /* Codec type */
-#define BTIF_AV_CODEC_NONE       0xFF
+#define BTIF_AV_CODEC_NONE       0xF1
 #define BTIF_AV_CODEC_SBC        A2D_MEDIA_CT_SBC        /* SBC media codec type */
-
+#define BTIF_AV_CODEC_M24        A2D_MEDIA_CT_M24        /* AAC media codec type */
 #define BTIF_AV_CODEC_PCM        0x5                     /* Raw PCM */
 
 typedef UINT8 tBTIF_AV_CODEC_ID;
diff --git a/btif/include/btif_av_co.h b/btif/include/btif_av_co.h
index a6a5bfa..a60749a 100644
--- a/btif/include/btif_av_co.h
+++ b/btif/include/btif_av_co.h
@@ -1,4 +1,10 @@
 /******************************************************************************
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a contribution.
+ ******************************************************************************/
+
+/******************************************************************************
  *
  *  Copyright (C) 2009-2012 Broadcom Corporation
  *
@@ -24,15 +30,6 @@
 /*******************************************************************************
 **  Constants & Macros
 ********************************************************************************/
-
-enum
-{
-    BTIF_SV_AV_AA_SBC_INDEX = 0,
-    BTIF_SV_AV_AA_SBC_SINK_INDEX,
-    BTIF_SV_AV_AA_SEP_INDEX  /* Last index */
-};
-
-
 /*******************************************************************************
 **  Functions
 ********************************************************************************/
@@ -114,6 +111,39 @@
 
 /*******************************************************************************
  **
+ ** Function         bta_av_co_get_current_codec
+ **
+ ** Description      Get the current codec type.
+ **
+ ** Returns          Codec Type Value
+ **
+ *******************************************************************************/
+UINT8 bta_av_co_get_current_codec();
+
+/*******************************************************************************
+ **
+ ** Function         bta_av_co_get_current_codecInfo
+ **
+ ** Description      Get the current codec Info.
+ **
+ ** Returns          Returns  pointer to Info
+ **
+ *******************************************************************************/
+UINT8* bta_av_co_get_current_codecInfo();
+
+/*******************************************************************************
+ **
+ ** Function         bta_av_co_audio_get_codec_config
+ **
+ ** Description     Retrieves the current codec configuration.  On Failure return the default
+ **                      codec configuration.
+ **
+ ** Returns          TRUE if codec is SBC, FALSE otherwise
+ **
+ *******************************************************************************/
+BOOLEAN bta_av_co_audio_get_codec_config(UINT8 *p_sbc_config, UINT16 *p_minmtu, UINT8 type);
+/*******************************************************************************
+ **
  ** Function         bta_av_co_audio_get_sbc_config
  **
  ** Description      Retrieves the SBC codec configuration.  If the codec in use
@@ -123,6 +153,20 @@
  **
  *******************************************************************************/
 BOOLEAN bta_av_co_audio_get_sbc_config(tA2D_SBC_CIE *p_sbc_config, UINT16 *p_minmtu);
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+/*******************************************************************************
+ **
+ ** Function         bta_av_co_audio_get_aac_config
+ **
+ ** Description      Retrieves the AAC codec configuration.  If the codec in use
+ **                  is not AAC, return the default SBC codec configuration.
+ **
+ ** Returns          TRUE if codec is AAC, FALSE otherwise
+ **
+ *******************************************************************************/
+BOOLEAN bta_av_co_audio_get_aac_config(tA2D_AAC_CIE *p_aac_config, UINT16 *p_minmtu);
+#endif
+
 
 /*******************************************************************************
  **
@@ -171,4 +215,28 @@
  *******************************************************************************/
 BOOLEAN bta_av_co_get_remote_bitpool_pref(UINT8 *min, UINT8 *max);
 
+/*******************************************************************************
+ **
+ ** Function         bta_av_select_codec
+ **
+ ** Description      Select the current codec for the remote device selected
+ **                  for streaming.
+ **
+ ** Returns          Return current codec id
+ **
+ *******************************************************************************/
+UINT8 bta_av_select_codec(tBTA_AV_HNDL hdl);
+
+/*******************************************************************************
+ **
+ ** Function         bta_av_co_audio_is_aac_enabled
+ **
+ ** Description      Compares the given BD address family against the interop databse
+ **                  and return if AAC can be selected as a codec for streaming or not
+ **
+ ** Returns          TRUE if AAC is allowed , FALSE otherwise
+ **
+ *******************************************************************************/
+BOOLEAN bta_av_co_audio_is_aac_enabled(bt_bdaddr_t *remote_bdaddr);
+
 #endif
diff --git a/btif/include/btif_common.h b/btif/include/btif_common.h
index b48631b..83ab28e 100644
--- a/btif/include/btif_common.h
+++ b/btif/include/btif_common.h
@@ -34,7 +34,7 @@
 ********************************************************************************/
 
 #define ASSERTC(cond, msg, val) if (!(cond)) { LOG_ERROR(LOG_TAG, \
-    "### ASSERT : %s line %d %s (%d) ###", __FILE__, __LINE__, msg, val);}
+    "### ASSERT : %s %s line %d %s (%d) ###", __FILE__, __func__, __LINE__, msg, val);}
 
 /* Calculate start of event enumeration; id is top 8 bits of event */
 #define BTIF_SIG_START(id)       ((id) << 8)
@@ -125,7 +125,9 @@
     BTIF_DM_CB_HID_REMOTE_NAME,   /* Remote name callback for HID device */
     BTIF_DM_CB_BOND_STATE_BONDING,
     BTIF_DM_CB_LE_TX_TEST,    /* BLE Tx Test command complete callback */
+    BTIF_DM_CB_LE_ENH_TX_TEST,    /* BLE Enh Tx Test command complete callback */
     BTIF_DM_CB_LE_RX_TEST,    /* BLE Rx Test command complete callback */
+    BTIF_DM_CB_LE_ENH_RX_TEST,    /* BLE Enh Rx Test command complete callback */
     BTIF_DM_CB_LE_TEST_END,   /* BLE Test mode end callback */
 
     BTIF_HFP_CB_START  = BTIF_SIG_CB_START(BTIF_HFP),
@@ -138,6 +140,19 @@
     BTIF_HF_CLIENT_CB_AUDIO_CONNECTING, /* AUDIO connect has been sent to BTA successfully */
 };
 
+/*
+ * Logger preference, based on which the Bluetooth logging is
+ * enabled.
+ */
+#ifdef BLUEDROID_DEBUG
+typedef enum {
+    CONFIG_PREFERENCE_FALSE = 0,
+    CONFIG_PREFERENCE_TRUE,
+    DEV_OPT_PREFERENCE,
+    NO_PREFERENCE,
+} logging_preference_t;
+#endif
+
 /* Macro definitions for BD ADDR persistence */
 
 /**
@@ -216,4 +231,6 @@
 
 void btif_init_ok(UNUSED_ATTR uint16_t event, UNUSED_ATTR char *p_param);
 
+void btif_ssr_cleanup(void);
+
 #endif /* BTIF_COMMON_H */
diff --git a/btif/include/btif_gatt_multi_adv_util.h b/btif/include/btif_gatt_multi_adv_util.h
index ac8351c..b009875 100644
--- a/btif/include/btif_gatt_multi_adv_util.h
+++ b/btif/include/btif_gatt_multi_adv_util.h
@@ -47,6 +47,7 @@
     uint8_t* p_service_data;
     uint16_t service_uuid_len;
     uint8_t* p_service_uuid;
+    uint8_t frag_preference;
 } btif_adv_data_t;
 
 
@@ -58,7 +59,8 @@
     tBTA_BLE_ADV_PARAMS param;
     alarm_t *multi_adv_timer;
     int timeout_s;
-} btgatt_multi_adv_inst_cb;
+    UINT8 frag_preference;
+}btgatt_multi_adv_inst_cb;
 
 typedef struct
 {
diff --git a/btif/include/btif_gatt_util.h b/btif/include/btif_gatt_util.h
index 715e0c5..1dff7cf 100644
--- a/btif/include/btif_gatt_util.h
+++ b/btif/include/btif_gatt_util.h
@@ -26,7 +26,7 @@
 
 void btif_to_bta_uuid(tBT_UUID *p_dest, bt_uuid_t *p_src);
 void btif_to_bta_response(tBTA_GATTS_RSP *p_dest, btgatt_response_t* p_src);
-void btif_to_bta_uuid_mask(tBTA_DM_BLE_PF_COND_MASK *p_mask, bt_uuid_t *p_src);
+void btif_to_bta_uuid_mask(tBTA_DM_BLE_PF_COND_MASK *p_mask, bt_uuid_t *p_src, bt_uuid_t *svc_uuid);
 
 void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src);
 
diff --git a/btif/include/btif_hh.h b/btif/include/btif_hh.h
index cf9731f..b58be36 100644
--- a/btif/include/btif_hh.h
+++ b/btif/include/btif_hh.h
@@ -25,20 +25,25 @@
 #include <stdint.h>
 #include "bta_hh_api.h"
 #include "btu.h"
-
+#include "osi/include/list.h"
 
 /*******************************************************************************
 **  Constants & Macros
 ********************************************************************************/
 
+#ifndef MAX_ACL_CONNECTIONS
 #define BTIF_HH_MAX_HID         8
+#else
+#define BTIF_HH_MAX_HID         MAX_ACL_CONNECTIONS
+#endif
+
 #define BTIF_HH_MAX_ADDED_DEV   32
 
 #define BTIF_HH_MAX_KEYSTATES            3
 #define BTIF_HH_KEYSTATE_MASK_NUMLOCK    0x01
 #define BTIF_HH_KEYSTATE_MASK_CAPSLOCK   0x02
 #define BTIF_HH_KEYSTATE_MASK_SCROLLLOCK 0x04
-
+#define BTIF_HH_OUTPUT_REPORT_SIZE       2
 
 /*******************************************************************************
 **  Type definitions and return values
@@ -68,7 +73,10 @@
     pthread_t                     hh_poll_thread_id;
     UINT8                         hh_keep_polling;
     alarm_t                       *vup_timer;
+    list_t                        *set_rpt_id_list; // Owns a collection of set_rpt_id objects.
+    UINT8                         get_rpt_snt;
     BOOLEAN                       local_vup; // Indicated locally initiated VUP
+    UINT8                         last_output_rpt_data[BTIF_HH_OUTPUT_REPORT_SIZE];
 } btif_hh_device_t;
 
 /* Control block to maintain properties of devices */
@@ -106,6 +114,8 @@
 extern void btif_hh_disconnect(bt_bdaddr_t *bd_addr);
 extern void btif_hh_setreport(btif_hh_device_t *p_dev, bthh_report_type_t r_type,
                     UINT16 size, UINT8* report);
+extern void btif_hh_getreport(btif_hh_device_t *p_dev, bthh_report_type_t r_type,
+                    UINT8 reportId, UINT16 bufferSize);
 
 BOOLEAN btif_hh_add_added_dev(bt_bdaddr_t bd_addr, tBTA_HH_ATTR_MASK attr_mask);
 
diff --git a/btif/include/btif_media.h b/btif/include/btif_media.h
index d432260..3046f60 100644
--- a/btif/include/btif_media.h
+++ b/btif/include/btif_media.h
@@ -1,4 +1,10 @@
 /******************************************************************************
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a contribution.
+ ******************************************************************************/
+
+/******************************************************************************
  *
  *  Copyright (C) 2009-2012 Broadcom Corporation
  *
@@ -32,7 +38,7 @@
 #include "bta_api.h"
 #include "bt_common.h"
 #include "btif_av_api.h"
-#include "audio_a2dp_hw.h"
+#include "a2d_aac.h"
 
 /*******************************************************************************
  **  Constants
@@ -54,7 +60,8 @@
 /* Transcoding definition for TxTranscoding and RxTranscoding */
 #define BTIF_MEDIA_TRSCD_OFF             0
 #define BTIF_MEDIA_TRSCD_PCM_2_SBC       1  /* Tx */
-
+#define BTIF_MEDIA_TRSCD_PCM_2_APTX      2
+#define BTIF_MEDIA_TRSCD_PCM_2_APTX_HD   3
 
 /*******************************************************************************
  **  Data types
@@ -72,6 +79,14 @@
         UINT8 NumOfBlocks; /* 4, 8, 12 or 16*/
         UINT8 AllocationMethod; /* loudness or SNR*/
         UINT16 MtuSize; /* peer mtu size */
+        UINT8 CodecType; /* SBC or Non-A2DP */
+        UINT32 BluetoothVendorID; /* Bluetooth Vendor ID */
+        UINT16 BluetoothCodecID; /* Bluetooth Codec ID */
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+        UINT8 ObjectType;
+        UINT32 bit_rate;
+        UINT8 vbr;
+#endif
 } tBTIF_MEDIA_INIT_AUDIO;
 
 #if (BTA_AV_INCLUDED == TRUE)
@@ -82,6 +97,9 @@
         UINT16 MinMtuSize; /* Minimum peer mtu size */
         UINT8 MaxBitPool; /* Maximum peer bitpool */
         UINT8 MinBitPool; /* Minimum peer bitpool */
+        UINT8 CodecType; /* SBC or Non-A2DP */
+        UINT32 BluetoothVendorID; /* Bluetooth Vendor ID */
+        UINT16 BluetoothCodecID; /* Bluetooth Codec ID */
 } tBTIF_MEDIA_UPDATE_AUDIO;
 
 /* tBTIF_MEDIA_INIT_AUDIO_FEEDING msg structure */
@@ -272,24 +290,37 @@
 
 bool btif_a2dp_start_media_task(void);
 void btif_a2dp_stop_media_task(void);
-
+bool btif_a2dp_is_media_task_stopped(void);
 void btif_a2dp_on_init(void);
-void btif_a2dp_setup_codec(void);
+tBTIF_STATUS btif_a2dp_setup_codec(tBTA_AV_HNDL hdl);
+void btif_a2dp_update_codec(void);
 void btif_a2dp_on_idle(void);
 void btif_a2dp_on_open(void);
-BOOLEAN btif_a2dp_on_started(tBTA_AV_START *p_av, BOOLEAN pending_start);
+BOOLEAN btif_a2dp_on_started(tBTA_AV_START *p_av, BOOLEAN pending_start, tBTA_AV_HNDL hdl);
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+void btif_media_on_stop_vendor_command();
+void btif_media_send_reset_vendor_state();
+BOOLEAN btif_media_send_vendor_start();
+void btif_media_start_vendor_command();
+#else
+#define btif_media_on_stop_vendor_command() (0)
+#define btif_media_send_reset_vendor_state() (0)
+#define btif_media_send_vendor_start() (0)
+#define btif_media_start_vendor_command() (0)
+#endif
+void btif_a2dp_on_remote_started();
 void btif_a2dp_ack_fail(void);
 void btif_a2dp_on_stop_req(void);
 void btif_a2dp_on_stopped(tBTA_AV_SUSPEND *p_av);
 void btif_a2dp_on_suspend(void);
 void btif_a2dp_on_suspended(tBTA_AV_SUSPEND *p_av);
+UINT8 btif_a2dp_get_pending_hal_command();
 void btif_a2dp_set_tx_flush(BOOLEAN enable);
 void btif_a2dp_set_rx_flush(BOOLEAN enable);
 void btif_media_check_iop_exceptions(UINT8 *peer_bda);
 void btif_reset_decoder(UINT8 *p_av);
 void btif_a2dp_on_offload_started(tBTA_AV_STATUS status);
 
-
 int btif_a2dp_get_track_frequency(UINT8 frequency);
 int btif_a2dp_get_track_channel_count(UINT8 channeltype);
 void btif_a2dp_set_peer_sep(UINT8 sep);
diff --git a/btif/include/btif_sm.h b/btif/include/btif_sm.h
index b4caf9e..b98936b 100644
--- a/btif/include/btif_sm.h
+++ b/btif/include/btif_sm.h
@@ -45,7 +45,7 @@
 typedef UINT32 btif_sm_state_t;
 typedef UINT32 btif_sm_event_t;
 typedef void* btif_sm_handle_t;
-typedef BOOLEAN(*btif_sm_handler_t)(btif_sm_event_t event, void *data);
+typedef BOOLEAN(*btif_sm_handler_t)(btif_sm_event_t event, void *data, int index);
 
 /*****************************************************************************
 **  Functions
@@ -67,7 +67,7 @@
 **
 ******************************************************************************/
 btif_sm_handle_t btif_sm_init(const btif_sm_handler_t *p_handlers,
-                               btif_sm_state_t initial_state);
+                               btif_sm_state_t initial_state, int index);
 
 /*****************************************************************************
 **
diff --git a/btif/include/btif_sock_rfc.h b/btif/include/btif_sock_rfc.h
index 7d93856..f80df3c 100644
--- a/btif/include/btif_sock_rfc.h
+++ b/btif/include/btif_sock_rfc.h
@@ -35,6 +35,10 @@
                               int* sock_fd, int flags, int app_uid);
 bt_status_t btsock_rfc_connect(const bt_bdaddr_t *bd_addr, const uint8_t* uuid,
                                int channel, int* sock_fd, int flags, int app_uid);
+bt_status_t btsock_rfc_get_sockopt(int channel, btsock_option_type_t option_name,
+                                            void *option_value, int *option_len);
+bt_status_t btsock_rfc_set_sockopt(int channel, btsock_option_type_t option_name,
+                                            void *option_value, int option_len);
 void btsock_rfc_signaled(int fd, int flags, uint32_t user_id);
 
 #endif
diff --git a/btif/include/btif_sock_sdp.h b/btif/include/btif_sock_sdp.h
index 7353cc9..674c4cd 100644
--- a/btif/include/btif_sock_sdp.h
+++ b/btif/include/btif_sock_sdp.h
@@ -33,6 +33,10 @@
                                                  0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
 static const uint8_t  UUID_SPP[]              = {0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00,
                                                  0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
+static const uint8_t  UUID_FTP[]              = {0x00, 0x00, 0x11, 0x06, 0x00, 0x00, 0x10, 0x00,
+                                                 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
+static const uint8_t  UUID_DUN[]              = {0x00, 0x00, 0x11, 0x03, 0x00, 0x00, 0x10, 0x00,
+                                                 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
 
 static inline bool is_uuid_empty(const uint8_t* uuid)
 {
diff --git a/btif/include/btif_storage.h b/btif/include/btif_storage.h
index 5309ce0..a0d04c0 100644
--- a/btif/include/btif_storage.h
+++ b/btif/include/btif_storage.h
@@ -138,6 +138,18 @@
 
 /*******************************************************************************
 **
+** Function         btif_storage_is_device_bonded
+**
+* Description      BTIF storage API - checks if device present in bonded list
+**
+** Returns          TRUE if the device is bonded,
+**                  FALSE otherwise
+**
+*******************************************************************************/
+BOOLEAN btif_storage_is_device_bonded(bt_bdaddr_t *remote_bd_addr);
+
+/*******************************************************************************
+**
 ** Function         btif_storage_remove_bonded_device
 **
 ** Description      BTIF storage API - Deletes the bonded device from NVRAM
diff --git a/btif/src/bluetooth.c b/btif/src/bluetooth.c
index 81964db..a264f32 100644
--- a/btif/src/bluetooth.c
+++ b/btif/src/bluetooth.c
@@ -31,7 +31,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-
+#include <cutils/properties.h>
 #include <hardware/bluetooth.h>
 #include <hardware/bt_av.h>
 #include <hardware/bt_gatt.h>
@@ -44,9 +44,15 @@
 #include <hardware/bt_rc.h>
 #include <hardware/bt_sdp.h>
 #include <hardware/bt_sock.h>
+#include <hardware/vendor.h>
+#ifdef WIPOWER_SUPPORTED
+#include <hardware/wipower.h>
+#endif
 
 #include "bt_utils.h"
 #include "btif_api.h"
+#include "btif_common.h"
+#include "device/include/controller.h"
 #include "btif_debug.h"
 #include "btsnoop.h"
 #include "btsnoop_mem.h"
@@ -64,6 +70,17 @@
 #include "btif/include/btif_debug_conn.h"
 #include "btif/include/btif_debug_l2c.h"
 #include "btif/include/btif_media.h"
+#include "l2cdefs.h"
+#include "l2c_api.h"
+#include "stack_config.h"
+
+#if TEST_APP_INTERFACE == TRUE
+#include <bt_testapp.h>
+#endif
+
+
+#include <logging.h>
+
 
 /************************************************************************************
 **  Static variables
@@ -102,9 +119,31 @@
 /* avrc target */
 extern btrc_interface_t *btif_rc_get_interface();
 /* avrc controller */
+#ifdef WIPOWER_SUPPORTED
+extern wipower_interface_t *get_wipower_interface();
+#endif
 extern btrc_interface_t *btif_rc_ctrl_get_interface();
 /*SDP search client*/
 extern btsdp_interface_t *btif_sdp_get_interface();
+/* vendor  */
+extern btvendor_interface_t *btif_vendor_get_interface();
+
+extern const btstacklog_interface_t *btif_stack_log_interface(void);
+#if TEST_APP_INTERFACE == TRUE
+extern const btl2cap_interface_t *btif_l2cap_get_interface(void);
+extern const btrfcomm_interface_t *btif_rfcomm_get_interface(void);
+extern const btmcap_interface_t *btif_mcap_get_interface(void);
+extern const btgatt_test_interface_t *btif_gatt_test_get_interface(void);
+extern const btsmp_interface_t *btif_smp_get_interface(void);
+extern const btgap_interface_t *btif_gap_get_interface(void);
+#endif
+
+extern void set_logging_pref(uint16_t pref_val);
+#ifdef BLUEDROID_DEBUG
+extern void enable_bt_logger_debug(bool);
+#else
+extern void enable_bt_logger(bool);
+#endif
 
 /************************************************************************************
 **  Functions
@@ -164,6 +203,9 @@
 
 static void cleanup(void) {
   stack_manager_get_interface()->clean_up_stack();
+
+  if(bt_logger_enabled)
+    property_set("bluetooth.startbtlogger", "false");
 }
 
 bool is_restricted_mode() {
@@ -377,6 +419,9 @@
     if (is_profile(profile_id, BT_PROFILE_SOCKETS_ID))
         return btif_sock_get_interface();
 
+    if (is_profile(profile_id, "LOG_ID"))
+        return btif_stack_log_interface();
+
     if (is_profile(profile_id, BT_PROFILE_PAN_ID))
         return btif_pan_get_interface();
 
@@ -403,12 +448,49 @@
     if (is_profile(profile_id, BT_PROFILE_AV_RC_ID))
         return btif_rc_get_interface();
 
+#ifdef WIPOWER_SUPPORTED
+    if (is_profile(profile_id, BT_PROFILE_WIPOWER_VENDOR_ID))
+        return get_wipower_interface();
+#endif
+
     if (is_profile(profile_id, BT_PROFILE_AV_RC_CTRL_ID))
         return btif_rc_ctrl_get_interface();
 
+    if (is_profile(profile_id, BT_PROFILE_VENDOR_ID))
+        return btif_vendor_get_interface();
+
     return NULL;
 }
 
+#if TEST_APP_INTERFACE == TRUE
+static const void* get_testapp_interface(int test_app_profile)
+{
+    ALOGI("get_testapp_interface %d", test_app_profile);
+
+    if (interface_ready() == FALSE) {
+        return NULL;
+    }
+    switch(test_app_profile) {
+        case TEST_APP_L2CAP:
+            return btif_l2cap_get_interface();
+        case TEST_APP_RFCOMM:
+            return btif_rfcomm_get_interface();
+        case TEST_APP_MCAP:
+           return btif_mcap_get_interface();
+        case TEST_APP_GATT:
+           return btif_gatt_test_get_interface();
+        case TEST_APP_SMP:
+           return btif_smp_get_interface();
+        case TEST_APP_GAP:
+           return btif_gap_get_interface();
+        default:
+            return NULL;
+    }
+    return NULL;
+}
+
+#endif //TEST_APP_INTERFACE
+
 int dut_mode_configure(uint8_t enable)
 {
     LOG_INFO(LOG_TAG, "dut_mode_configure");
@@ -431,6 +513,19 @@
     return btif_dut_mode_send(opcode, buf, len);
 }
 
+#if HCI_RAW_CMD_INCLUDED == TRUE
+int hci_cmd_send(uint16_t opcode, uint8_t* buf, uint8_t len)
+{
+    ALOGI("hci_cmd_send");
+
+    /* sanity check */
+    if (interface_ready() == FALSE || stack_manager_get_interface()->get_stack_is_running() == FALSE)
+        return BT_STATUS_NOT_READY;
+
+    return btif_hci_cmd_send(opcode, buf, len);
+}
+#endif
+
 #if BLE_INCLUDED == TRUE
 int le_test_mode(uint16_t opcode, uint8_t* buf, uint8_t len)
 {
@@ -451,7 +546,15 @@
     if (!interface_ready())
         return BT_STATUS_NOT_READY;
 
+#ifdef BLUEDROID_DEBUG
+    enable_bt_logger_debug(enable);
+#else
+    enable_bt_logger(enable);
+#endif
+
     btsnoop_get_interface()->set_api_wants_to_log(enable);
+    controller_get_static_interface()->enable_soc_logging(enable);
+
     return BT_STATUS_SUCCESS;
 }
 
@@ -491,6 +594,11 @@
     get_profile_interface,
     dut_mode_configure,
     dut_mode_send,
+#if HCI_RAW_CMD_INCLUDED == TRUE
+    hci_cmd_send,
+#else
+    NULL,
+#endif
 #if BLE_INCLUDED == TRUE
     le_test_mode,
 #else
@@ -503,6 +611,11 @@
     config_clear,
     interop_database_clear,
     interop_database_add,
+#if TEST_APP_INTERFACE == TRUE
+    get_testapp_interface,
+#else
+    NULL,
+#endif
 };
 
 const bt_interface_t* bluetooth__get_bluetooth_interface ()
diff --git a/btif/src/btif_av.c b/btif/src/btif_av.c
old mode 100644
new mode 100755
index f852d48..ee05fa0
--- a/btif/src/btif_av.c
+++ b/btif/src/btif_av.c
@@ -1,4 +1,6 @@
 /******************************************************************************
+ *  Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *  Not a Contribution.
  *
  *  Copyright (C) 2009-2012 Broadcom Corporation
  *
@@ -35,6 +37,10 @@
 #include "btu.h"
 #include "bt_common.h"
 #include "osi/include/allocator.h"
+#include <cutils/properties.h>
+#include "device/include/interop.h"
+#include "btif_storage.h"
+#include "audio_a2dp_hw.h"
 
 /*****************************************************************************
 **  Constants & Macros
@@ -43,6 +49,13 @@
 #define BTIF_AVK_SERVICE_NAME "Advanced Audio Sink"
 
 #define BTIF_TIMEOUT_AV_OPEN_ON_RC_MS  (2 * 1000)
+#define BTIF_TIMEOUT_AV_COLL_DETECTED_MS (2 * 1000)
+
+/* Number of BTIF-AV control blocks */
+/* Now supports Two AV connections. */
+#define BTIF_AV_NUM_CB       2
+#define HANDLE_TO_INDEX(x) ((x & BTA_AV_HNDL_MSK) - 1)
+#define INVALID_INDEX        -1
 
 typedef enum {
     BTIF_AV_STATE_IDLE = 0x0,
@@ -61,6 +74,11 @@
 #define BTIF_AV_FLAG_REMOTE_SUSPEND        0x2
 #define BTIF_AV_FLAG_PENDING_START         0x4
 #define BTIF_AV_FLAG_PENDING_STOP          0x8
+#define BTIF_AV_FLAG_PENDING_DISCONNECT   0x10
+/* Host role defenitions */
+#define HOST_ROLE_MASTER                   0x00
+#define HOST_ROLE_SLAVE                    0x01
+#define HOST_ROLE_UNKNOWN                  0xff
 
 /*****************************************************************************
 **  Local type definitions
@@ -74,6 +92,18 @@
     UINT8 flags;
     tBTA_AV_EDR edr;
     UINT8 peer_sep;  /* sep type of peer device */
+    UINT8 edr_3mbps;
+    BOOLEAN dual_handoff;
+    BOOLEAN current_playing;
+    btif_sm_state_t state;
+    int service;
+    BOOLEAN is_slave;
+    BOOLEAN is_device_playing;
+    BOOLEAN is_remote_start_received;
+    BOOLEAN is_suspend_for_remote_start;
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+    UINT16 channel_id;
+#endif
 } btif_av_cb_t;
 
 typedef struct
@@ -89,17 +119,43 @@
     bt_bdaddr_t peer_bd;
 } btif_av_sink_config_req_t;
 
+typedef struct
+{
+    BOOLEAN sbc_offload;
+    BOOLEAN aptx_offload;
+    BOOLEAN aac_offload;
+    BOOLEAN aptxhd_offload;
+} btif_av_a2dp_offloaded_codec_cap_t;
+
+typedef enum {
+    SBC,
+    APTX,
+    AAC,
+    APTXHD,
+}btif_av_codec_list;
+
 /*****************************************************************************
 **  Static variables
 ******************************************************************************/
 static btav_callbacks_t *bt_av_src_callbacks = NULL;
 static btav_callbacks_t *bt_av_sink_callbacks = NULL;
-static btif_av_cb_t btif_av_cb = {0, {{0}}, 0, 0, 0, 0};
 static alarm_t *av_open_on_rc_timer = NULL;
-
+static alarm_t *av_coll_detected_timer = NULL;
+static bt_bdaddr_t retry_bda;
+static int conn_retry_count = 1;
+static btif_av_cb_t btif_av_cb[BTIF_AV_NUM_CB];
+static btif_sm_event_t idle_rc_event;
+static tBTA_AV idle_rc_data;
+int btif_max_av_clients = 1;
+static BOOLEAN enable_multicast = FALSE;
+static BOOLEAN is_multicast_supported = FALSE;
+static BOOLEAN multicast_disabled = FALSE;
+BOOLEAN bt_split_a2dp_enabled = FALSE;
+BOOLEAN reconfig_a2dp = FALSE;
+btif_av_a2dp_offloaded_codec_cap_t btif_av_codec_offload;
 /* both interface and media task needs to be ready to alloc incoming request */
 #define CHECK_BTAV_INIT() if (((bt_av_src_callbacks == NULL) &&(bt_av_sink_callbacks == NULL)) \
-        || (btif_av_cb.sm_handle == NULL))\
+        || (btif_av_cb[0].sm_handle == NULL))\
 {\
      BTIF_TRACE_WARNING("%s: BTAV not initialized", __FUNCTION__);\
      return BT_STATUS_NOT_READY;\
@@ -111,23 +167,40 @@
 
 /* Helper macro to avoid code duplication in the state machine handlers */
 #define CHECK_RC_EVENT(e, d) \
-    case BTA_AV_RC_OPEN_EVT: \
     case BTA_AV_RC_CLOSE_EVT: \
     case BTA_AV_REMOTE_CMD_EVT: \
     case BTA_AV_VENDOR_CMD_EVT: \
     case BTA_AV_META_MSG_EVT: \
+    case BTA_AV_BROWSE_MSG_EVT: \
     case BTA_AV_RC_FEAT_EVT: \
     case BTA_AV_REMOTE_RSP_EVT: \
     { \
          btif_rc_handler(e, d);\
     }break; \
 
-static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *data);
-static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *data);
-static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *data);
-static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *data);
-static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *data);
 
+static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *data, int index);
+static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *data, int index);
+static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *data, int index);
+static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *data,int index);
+
+static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *data,int index);
+
+static BOOLEAN btif_av_get_valid_idx(int idx);
+UINT8 btif_av_idx_by_bdaddr( BD_ADDR bd_addr);
+int btif_get_latest_playing_device_idx();
+static int btif_get_latest_device_idx_to_start();
+static int btif_av_get_valid_idx_for_rc_events(BD_ADDR bd_addr, int rc_handle);
+static int btif_get_conn_state_of_device(BD_ADDR address);
+static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid);
+static void btif_av_update_current_playing_device(int index);
+static void btif_av_check_rc_connection_priority(void *p_data);
+static int btif_get_is_remote_started_idx();
+static void btif_av_reset_remote_started_flag();
+
+#ifdef AVK_BACKPORT
+void btif_av_request_audio_focus( BOOLEAN enable);
+#endif
 static const btif_sm_handler_t btif_av_state_handlers[] =
 {
     btif_av_state_idle_handler,
@@ -144,14 +217,46 @@
 *************************************************************************/
 extern void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data);
 extern BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr);
-extern UINT8 btif_rc_get_connected_peer_handle(void);
+extern UINT8 btif_rc_get_connected_peer_handle(BD_ADDR peer_addr);
 extern void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, BOOLEAN bSendToApp);
+extern void btif_rc_get_playing_device(BD_ADDR address);
+extern void btif_rc_clear_playing_state(BOOLEAN play);
+extern void btif_rc_clear_priority(BD_ADDR address);
+extern void btif_rc_send_pause_command();
+extern UINT16 btif_dm_get_br_edr_links();
+extern UINT16 btif_dm_get_le_links();
+extern UINT16 btif_hf_is_call_vr_idle();
+extern void btif_media_on_cancel_remote_start_alarm();
 
 extern fixed_queue_t *btu_general_alarm_queue;
 
 /*****************************************************************************
 ** Local helper functions
 ******************************************************************************/
+void btif_av_trigger_dual_handoff(BOOLEAN handoff, BD_ADDR address);
+BOOLEAN btif_av_is_device_connected(BD_ADDR address);
+
+BOOLEAN btif_av_is_connected_on_other_idx(int current_index);
+BOOLEAN btif_av_is_playing_on_other_idx(int current_index);
+BOOLEAN btif_av_is_playing();
+void btif_av_update_multicast_state(int index);
+BOOLEAN btif_av_get_ongoing_multicast();
+tBTA_AV_HNDL btif_av_get_playing_device_hdl();
+tBTA_AV_HNDL btif_av_get_av_hdl_from_idx(UINT8 idx);
+int btif_av_get_other_connected_idx(int current_index);
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+BOOLEAN btif_av_is_codec_offload_supported(int codec);
+BOOLEAN btif_av_is_under_handoff();
+void btif_av_reset_reconfig_flag();
+BOOLEAN btif_av_is_device_disconnecting();
+BOOLEAN btif_av_is_suspend_stop_pending_ack();
+#else
+#define btif_av_is_codec_offload_supported(codec) (0)
+#define btif_av_is_under_handoff() (0)
+#define btif_av_reset_reconfig_flag() (0)
+#define btif_av_is_device_disconnecting() (0)
+#define btif_av_is_suspend_stop_pending_ack() (0)
+#endif
 
 const char *dump_av_sm_state_name(btif_av_state_t state)
 {
@@ -198,15 +303,31 @@
         CASE_RETURN_STR(BTIF_AV_START_STREAM_REQ_EVT)
         CASE_RETURN_STR(BTIF_AV_STOP_STREAM_REQ_EVT)
         CASE_RETURN_STR(BTIF_AV_SUSPEND_STREAM_REQ_EVT)
+        CASE_RETURN_STR(BTIF_AV_REMOTE_SUSPEND_STREAM_REQ_EVT)
         CASE_RETURN_STR(BTIF_AV_SINK_CONFIG_REQ_EVT)
         CASE_RETURN_STR(BTIF_AV_OFFLOAD_START_REQ_EVT)
 #ifdef USE_AUDIO_TRACK
         CASE_RETURN_STR(BTIF_AV_SINK_FOCUS_REQ_EVT)
 #endif
+        CASE_RETURN_STR(BTIF_AV_UPDATE_ENCODER_REQ_EVT)
         default: return "UNKNOWN_EVENT";
    }
 }
 
+const char *dump_av_codec_name(btif_av_codec_list codec)
+{
+    switch((int)codec)
+    {
+        CASE_RETURN_STR(SBC)
+        CASE_RETURN_STR(APTX)
+        CASE_RETURN_STR(AAC)
+        CASE_RETURN_STR(APTXHD)
+        default: return "UNKNOWN_CODEC";
+    }
+}
+//TODO.. We will remove this data structure
+static BD_ADDR bd_null= {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
 /****************************************************************************
 **  Local helper functions
 *****************************************************************************/
@@ -224,25 +345,49 @@
 static void btif_initiate_av_open_timer_timeout(UNUSED_ATTR void *data)
 {
     BD_ADDR peer_addr;
-    btif_av_connect_req_t connect_req;
 
     /* is there at least one RC connection - There should be */
-    if (btif_rc_get_connected_peer(peer_addr)) {
-       BTIF_TRACE_DEBUG("%s Issuing connect to the remote RC peer", __FUNCTION__);
-       /* In case of AVRCP connection request, we will initiate SRC connection */
-       connect_req.target_bda = (bt_bdaddr_t*)&peer_addr;
-       if(bt_av_sink_callbacks != NULL)
-           connect_req.uuid = UUID_SERVCLASS_AUDIO_SINK;
-       else if(bt_av_src_callbacks != NULL)
-           connect_req.uuid = UUID_SERVCLASS_AUDIO_SOURCE;
-       btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char*)&connect_req);
+    /*We have Two Connections.*/
+    if (btif_rc_get_connected_peer(peer_addr))
+    {
+        /*Check if this peer_addr is same as currently connected AV*/
+        if (btif_get_conn_state_of_device(peer_addr) == BTIF_AV_STATE_OPENED)
+        {
+            BTIF_TRACE_DEBUG("AV is already connected");
+        }
+        else
+        {
+            UINT8 rc_handle;
+            int index;
+            /* Multicast: Check if AV slot is available for connection
+             * If not available, AV got connected to different devices.
+             * Disconnect this RC connection without AV connection.
+             */
+            rc_handle = btif_rc_get_connected_peer_handle(peer_addr);
+            index = btif_av_get_valid_idx_for_rc_events(peer_addr, rc_handle);
+            if(index >= btif_max_av_clients)
+            {
+                BTIF_TRACE_ERROR("%s No slot free for AV connection, back off",
+                            __FUNCTION__);
+                return;
+            }
+            BTIF_TRACE_DEBUG("%s Issuing connect to the remote RC peer", __FUNCTION__);
+            if(bt_av_sink_callbacks != NULL)
+                btif_queue_connect(UUID_SERVCLASS_AUDIO_SINK, (bt_bdaddr_t*)&peer_addr,
+                        connect_int);
+            if(bt_av_src_callbacks != NULL)
+                btif_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, (bt_bdaddr_t*)&peer_addr,
+                        connect_int);
+        }
     }
     else
     {
         BTIF_TRACE_ERROR("%s No connected RC peers", __FUNCTION__);
     }
+
 }
 
+
 /*****************************************************************************
 **  Static functions
 ******************************************************************************/
@@ -261,7 +406,7 @@
 {
     if (bt_av_sink_callbacks != NULL) {
         HAL_CBACK(bt_av_sink_callbacks, connection_state_cb, state, bd_addr);
-    } else if (bt_av_src_callbacks != NULL) {
+    } else if ( bt_av_src_callbacks != NULL) {
         HAL_CBACK(bt_av_src_callbacks, connection_state_cb, state, bd_addr);
     }
 }
@@ -288,6 +433,90 @@
     }
 }
 
+static void btif_av_collission_timer_timeout(UNUSED_ATTR void *data)
+{
+    bt_bdaddr_t *target_bda = &retry_bda;
+    btif_sm_state_t av_state;
+    BD_ADDR av_address;
+
+    bdcpy(av_address, target_bda->address);
+    av_state = btif_get_conn_state_of_device(av_address);
+    BTIF_TRACE_IMP("btif_av_collission_timer_timeout: AV state: %d", av_state);
+    BTIF_TRACE_IMP("TARGET BD ADDRESS %x:%x:%x:%x:%x:%x", av_address[0],
+        av_address[1], av_address[2], av_address[3], av_address[4], av_address[5]);
+
+    if (av_state == BTIF_AV_STATE_IDLE && conn_retry_count <= 1)
+    {
+        if (bt_av_src_callbacks != NULL)
+        {
+            BTIF_TRACE_IMP("%s Starting A2dp connection", __FUNCTION__);
+            conn_retry_count++;
+            btif_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, target_bda, connect_int);
+        }
+        else
+        {
+            BTIF_TRACE_IMP("%s Aborting A2dp connection retry", __FUNCTION__);
+        }
+    }
+    else if (btif_rc_get_connected_peer_handle(av_address) == BTIF_RC_HANDLE_NONE
+            && conn_retry_count <= 1)
+    {
+        tBTA_AV_HNDL handle;
+        UINT8 idx = btif_av_idx_by_bdaddr(av_address);
+        if (idx == btif_max_av_clients)
+        {
+            BTIF_TRACE_ERROR("%s: Invalid handle",__func__);
+            handle = (tBTA_AV_HNDL)INVALID_INDEX;
+        }
+        else
+        {
+            handle = btif_av_cb[idx].bta_handle;
+        }
+        BTIF_TRACE_IMP("%s Starting Avrcp connection for handle: %d", __FUNCTION__, handle);
+        if ((handle != (tBTA_AV_HNDL)INVALID_INDEX) && (bt_av_src_callbacks != NULL))
+        {
+            BTA_AvOpenRc(handle);
+            conn_retry_count++;
+        }
+        else
+        {
+            BTIF_TRACE_IMP("%s Aborting Avrcp connection retry", __FUNCTION__);
+        }
+    }
+    else
+    {
+        if (conn_retry_count > 1)
+        {
+            conn_retry_count = 1;
+            BTIF_TRACE_IMP("%s Connection Retry count exceeded", __FUNCTION__);
+            return;
+        }
+        BTIF_TRACE_IMP("%s A2dp already connected", __FUNCTION__);
+        BTIF_TRACE_IMP("%s Avrcp already connected on handle: %d", __FUNCTION__,
+            btif_rc_get_connected_peer_handle(av_address));
+    }
+}
+
+
+void btif_av_check_and_start_collission_timer(int index)
+{
+    memcpy(&retry_bda, &btif_av_cb[index].peer_bda, sizeof(bt_bdaddr_t));
+
+    BTIF_TRACE_IMP("btif_av_check_and_start_collission_timer, index: %d ", index);
+
+    if (alarm_is_scheduled(av_coll_detected_timer))
+    {
+        alarm_cancel(av_coll_detected_timer);
+        BTIF_TRACE_IMP("btif_av_check_and_start_collission_timer:Deleting previously queued timer");
+    }
+    alarm_set_on_queue(av_coll_detected_timer,
+              BTIF_TIMEOUT_AV_COLL_DETECTED_MS,
+              btif_av_collission_timer_timeout,
+              NULL,
+              btu_general_alarm_queue);
+}
+
+
 /*****************************************************************************
 **
 ** Function     btif_av_state_idle_handler
@@ -298,75 +527,76 @@
 **
 *******************************************************************************/
 
-static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data)
+static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data, int index)
 {
-    BTIF_TRACE_DEBUG("%s event:%s flags %x", __FUNCTION__,
-                     dump_av_sm_event_name(event), btif_av_cb.flags);
+    char a2dp_role[255] = "false";
+
+    BTIF_TRACE_IMP("%s event:%s flags %x on Index = %d", __FUNCTION__,
+                     dump_av_sm_event_name(event), btif_av_cb[index].flags, index);
 
     switch (event)
     {
         case BTIF_SM_ENTER_EVT:
             /* clear the peer_bda */
-            memset(&btif_av_cb.peer_bda, 0, sizeof(bt_bdaddr_t));
-            btif_av_cb.flags = 0;
-            btif_av_cb.edr = 0;
-            btif_a2dp_on_idle();
+            BTIF_TRACE_EVENT("IDLE state for index: %d", index);
+            memset(&btif_av_cb[index].peer_bda, 0, sizeof(bt_bdaddr_t));
+            btif_av_cb[index].flags = 0;
+            btif_av_cb[index].edr_3mbps = 0;
+            btif_av_cb[index].edr = 0;
+            btif_av_cb[index].current_playing = FALSE;
+            btif_av_cb[index].is_slave = FALSE;
+            btif_av_cb[index].is_remote_start_received = FALSE;
+            btif_av_cb[index].is_suspend_for_remote_start = FALSE;
+            btif_av_cb[index].is_device_playing = FALSE;
+            for (int i = 0; i < btif_max_av_clients; i++)
+            {
+                btif_av_cb[i].dual_handoff = FALSE;
+            }
+            property_get("persist.service.bt.a2dp.sink", a2dp_role, "false");
+            if (!strncmp("false", a2dp_role, 5)) {
+                btif_av_cb[index].peer_sep = AVDT_TSEP_SNK;
+                btif_a2dp_set_peer_sep(AVDT_TSEP_SNK);
+            } else {
+                btif_av_cb[index].peer_sep = AVDT_TSEP_SRC;
+                btif_a2dp_set_peer_sep(AVDT_TSEP_SRC);
+            }
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+            btif_av_cb[index].channel_id = 0;
+#endif
+            /* This API will be called twice at initialization
+            ** Idle can be moved when device is disconnected too.
+            ** Take care of other connected device here.*/
+            if (!btif_av_is_connected())
+            {
+                BTIF_TRACE_EVENT("reset A2dp states in IDLE ");
+                btif_a2dp_on_idle();
+            }
+            else
+            {
+                //There is another AV connection, update current playin
+                BTIF_TRACE_EVENT("reset A2dp states in IDLE ");
+                //btif_media_send_reset_vendor_state();
+                btif_av_update_current_playing_device(index);
+            }
+            if (!btif_av_is_playing_on_other_idx(index) &&
+                 bt_split_a2dp_enabled)
+            {
+                BTIF_TRACE_EVENT("reset Vendor flag A2DP state is IDLE");
+                reconfig_a2dp = FALSE;
+                btif_media_send_reset_vendor_state();
+            }
             break;
 
         case BTIF_SM_EXIT_EVT:
             break;
 
         case BTA_AV_ENABLE_EVT:
+            BTIF_TRACE_EVENT("AV is enabled now for index: %d", index);
             break;
 
         case BTA_AV_REGISTER_EVT:
-            btif_av_cb.bta_handle = ((tBTA_AV*)p_data)->registr.hndl;
-            break;
-
-        case BTA_AV_PENDING_EVT:
-        case BTIF_AV_CONNECT_REQ_EVT:
-        {
-             if (event == BTIF_AV_CONNECT_REQ_EVT)
-             {
-                 memcpy(&btif_av_cb.peer_bda, ((btif_av_connect_req_t*)p_data)->target_bda,
-                                                                   sizeof(bt_bdaddr_t));
-                 BTA_AvOpen(btif_av_cb.peer_bda.address, btif_av_cb.bta_handle,
-                    TRUE, BTA_SEC_AUTHENTICATE, ((btif_av_connect_req_t*)p_data)->uuid);
-             }
-             else if (event == BTA_AV_PENDING_EVT)
-             {
-                  bdcpy(btif_av_cb.peer_bda.address, ((tBTA_AV*)p_data)->pend.bd_addr);
-                  if (bt_av_src_callbacks != NULL)
-                  {
-                      BTA_AvOpen(btif_av_cb.peer_bda.address, btif_av_cb.bta_handle,
-                        TRUE, BTA_SEC_AUTHENTICATE, UUID_SERVCLASS_AUDIO_SOURCE);
-                  }
-                  if (bt_av_sink_callbacks != NULL)
-                  {
-                      BTA_AvOpen(btif_av_cb.peer_bda.address, btif_av_cb.bta_handle,
-                                 TRUE, BTA_SEC_AUTHENTICATE, UUID_SERVCLASS_AUDIO_SINK);
-                  }
-             }
-             btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENING);
-        } break;
-
-        case BTA_AV_RC_OPEN_EVT:
-            /* IOP_FIX: Jabra 620 only does RC open without AV open whenever it connects. So
-             * as per the AV WP, an AVRC connection cannot exist without an AV connection. Therefore,
-             * we initiate an AV connection if an RC_OPEN_EVT is received when we are in AV_CLOSED state.
-             * We initiate the AV connection after a small 3s timeout to avoid any collisions from the
-             * headsets, as some headsets initiate the AVRC connection first and then
-             * immediately initiate the AV connection
-             *
-             * TODO: We may need to do this only on an AVRCP Play. FixMe
-             */
-
-            BTIF_TRACE_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV");
-            alarm_set_on_queue(av_open_on_rc_timer,
-                               BTIF_TIMEOUT_AV_OPEN_ON_RC_MS,
-                               btif_initiate_av_open_timer_timeout, NULL,
-                               btu_general_alarm_queue);
-            btif_rc_handler(event, p_data);
+            BTIF_TRACE_EVENT("The AV Handle:%d", ((tBTA_AV*)p_data)->registr.hndl);
+            btif_av_cb[index].bta_handle = ((tBTA_AV*)p_data)->registr.hndl;
             break;
 
            /*
@@ -390,47 +620,157 @@
             }
         } break;
 
+        case BTIF_AV_CONNECT_REQ_EVT:
+            /* For outgoing connect stack and app are in sync.
+            */
+            memcpy(&btif_av_cb[index].peer_bda, ((btif_av_connect_req_t*)p_data)->target_bda,
+                                                                        sizeof(bt_bdaddr_t));
+            BTA_AvOpen(btif_av_cb[index].peer_bda.address, btif_av_cb[index].bta_handle,
+                        TRUE, BTA_SEC_AUTHENTICATE, ((btif_av_connect_req_t*)p_data)->uuid);
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_OPENING);
+            break;
+
+        case BTA_AV_PENDING_EVT:
+        case BTA_AV_RC_OPEN_EVT:
+            /* IOP_FIX: Jabra 620 only does RC open without AV open whenever it connects. So
+             * as per the AV WP, an AVRC connection cannot exist without an AV connection. Therefore,
+             * we initiate an AV connection if an RC_OPEN_EVT is received when we are in AV_CLOSED state.
+             * We initiate the AV connection after a small 3s timeout to avoid any collisions from the
+             * headsets, as some headsets initiate the AVRC connection first and then
+             * immediately initiate the AV connection
+             *
+             * TODO: We may need to do this only on an AVRCP Play. FixMe
+             */
+            /* Check if connection allowed with this device */
+            /* In Dual A2dp case, this event can come for both the headsets.
+             * Reject second connection request as we are already checking
+             * for device priority for first device and we cannot queue
+             * incoming connections requests.
+             */
+
+            if (idle_rc_event != 0)
+            {
+                BTIF_TRACE_DEBUG("Processing another RC Event ");
+                return FALSE;
+            }
+            memcpy(&idle_rc_data, ((tBTA_AV*)p_data), sizeof(tBTA_AV));
+            if (event == BTA_AV_RC_OPEN_EVT)
+            {
+                if (((tBTA_AV*)p_data)->rc_open.status == BTA_AV_SUCCESS)
+                {
+                    bdcpy(btif_av_cb[index].peer_bda.address,
+                        ((tBTA_AV*)p_data)->rc_open.peer_addr);
+                }
+                else
+                {
+                    idle_rc_event = 0;
+                    return TRUE;
+                }
+            }
+            else
+            {
+                bdcpy(btif_av_cb[index].peer_bda.address, ((tBTA_AV*)p_data)->pend.bd_addr);
+            }
+
+            // Only for AVDTP connection request move to opening state
+            if (event == BTA_AV_PENDING_EVT)
+                btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_OPENING);
+
+            if (bt_av_src_callbacks != NULL)
+            {
+                BTIF_TRACE_DEBUG("Calling connection priority callback ");
+                idle_rc_event = event;
+                HAL_CBACK(bt_av_src_callbacks, connection_priority_cb,
+                         &(btif_av_cb[index].peer_bda));
+            }
+            if (bt_av_sink_callbacks != NULL)
+            {
+                if(event == BTA_AV_PENDING_EVT)
+                {
+                    BTA_AvOpen(btif_av_cb[index].peer_bda.address, btif_av_cb[index].bta_handle,
+                       TRUE, BTA_SEC_AUTHENTICATE, UUID_SERVCLASS_AUDIO_SINK);
+                }
+                else if(event == BTA_AV_RC_OPEN_EVT)
+                {
+ 		            alarm_set_on_queue(av_open_on_rc_timer,
+ 							  BTIF_TIMEOUT_AV_OPEN_ON_RC_MS,
+ 							  btif_initiate_av_open_timer_timeout, NULL,
+ 							  btu_general_alarm_queue);
+                    btif_rc_handler(event, p_data);
+                }
+            }
+            break;
+
         case BTA_AV_OPEN_EVT:
         {
+            /* We get this event in Idle State if Signaling
+             * channel is not closed, only Streaming channel was
+             * closed earlier, and now only stream setup process is
+             * initiated.
+             */
             tBTA_AV *p_bta_data = (tBTA_AV*)p_data;
             btav_connection_state_t state;
-            btif_sm_state_t av_state;
             BTIF_TRACE_DEBUG("status:%d, edr 0x%x",p_bta_data->open.status,
                                p_bta_data->open.edr);
 
             if (p_bta_data->open.status == BTA_AV_SUCCESS)
             {
                  state = BTAV_CONNECTION_STATE_CONNECTED;
-                 av_state = BTIF_AV_STATE_OPENED;
-                 btif_av_cb.edr = p_bta_data->open.edr;
-
-                 btif_av_cb.peer_sep = p_bta_data->open.sep;
+                 btif_av_cb[index].edr = p_bta_data->open.edr;
+                 if (p_bta_data->open.role == HOST_ROLE_SLAVE)
+                 {
+                    btif_av_cb[index].is_slave = TRUE;
+                 }
+                 btif_av_cb[index].peer_sep = p_bta_data->open.sep;
                  btif_a2dp_set_peer_sep(p_bta_data->open.sep);
+
+                 if ((p_bta_data->open.edr & BTA_AV_EDR_3MBPS) &&
+                     (!(interop_match_addr(INTEROP_2MBPS_LINK_ONLY,
+                        (const bt_bdaddr_t *)&btif_av_cb[index].peer_bda.address))))
+                 {
+                     BTIF_TRACE_DEBUG("remote supports 3 mbps");
+                     btif_av_cb[index].edr_3mbps = TRUE;
+                 }
+
+                 bdcpy(btif_av_cb[index].peer_bda.address, ((tBTA_AV*)p_data)->open.bd_addr);
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+                 btif_av_cb[index].channel_id = p_bta_data->open.stream_chnl_id;
+                 BTIF_TRACE_DEBUG("streaming channel id updated as : 0x%x",
+                    btif_av_cb[index].channel_id);
+#endif
             }
             else
             {
                 BTIF_TRACE_WARNING("BTA_AV_OPEN_EVT::FAILED status: %d",
                                      p_bta_data->open.status );
                 state = BTAV_CONNECTION_STATE_DISCONNECTED;
-                av_state  = BTIF_AV_STATE_IDLE;
             }
 
-            /* inform the application of the event */
-            btif_report_connection_state(state, &(btif_av_cb.peer_bda));
-            /* change state to open/idle based on the status */
-            btif_sm_change_state(btif_av_cb.sm_handle, av_state);
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+            /* change state to open based on the status */
+            if (p_bta_data->open.status == BTA_AV_SUCCESS)
+            {
+                /* inform the application of the event */
+                btif_report_connection_state(state, &(btif_av_cb[index].peer_bda));
+                btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_OPENED);
+                /* BTIF AV State updated, now check
+                 * and update multicast state
+                 */
+                btif_av_update_multicast_state(index);
+            }
+
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
             {
                 /* if queued PLAY command,  send it now */
                 btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr,
                                              (p_bta_data->open.status == BTA_AV_SUCCESS));
             }
-            else if (btif_av_cb.peer_sep == AVDT_TSEP_SRC)
+            else if ((btif_av_cb[index].peer_sep == AVDT_TSEP_SRC) &&
+                    (p_bta_data->open.status == BTA_AV_SUCCESS))
             {
                 /* if queued PLAY command,  send it now */
                 btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr, FALSE);
                 /* Bring up AVRCP connection too */
-                BTA_AvOpenRc(btif_av_cb.bta_handle);
+                BTA_AvOpenRc(btif_av_cb[index].bta_handle);
             }
             btif_queue_advance();
         } break;
@@ -440,6 +780,7 @@
         case BTA_AV_META_MSG_EVT:
         case BTA_AV_RC_FEAT_EVT:
         case BTA_AV_REMOTE_RSP_EVT:
+        case BTA_AV_BROWSE_MSG_EVT:
             btif_rc_handler(event, (tBTA_AV*)p_data);
             break;
 
@@ -454,6 +795,10 @@
             btif_a2dp_on_offload_started(BTA_AV_FAIL);
             break;
 
+        case BTA_AV_RC_COLL_DETECTED_EVT:
+            BTIF_TRACE_WARNING("BTA_AV_RC_COLL_DETECTED_EVT: Not Starting conn retry timer");
+            break;
+
         default:
             BTIF_TRACE_WARNING("%s : unhandled event:%s", __FUNCTION__,
                                 dump_av_sm_event_name(event));
@@ -474,16 +819,25 @@
 **
 *******************************************************************************/
 
-static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data)
+static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data, int index)
 {
-    BTIF_TRACE_DEBUG("%s event:%s flags %x", __FUNCTION__,
-                     dump_av_sm_event_name(event), btif_av_cb.flags);
-
+    int i;
+    BTIF_TRACE_IMP("%s event:%s flags %x on index = %d", __FUNCTION__,
+                     dump_av_sm_event_name(event), btif_av_cb[index].flags, index);
     switch (event)
     {
         case BTIF_SM_ENTER_EVT:
             /* inform the application that we are entering connecting state */
-            btif_report_connection_state(BTAV_CONNECTION_STATE_CONNECTING, &(btif_av_cb.peer_bda));
+            if (bt_av_sink_callbacks != NULL)
+            {
+                HAL_CBACK(bt_av_sink_callbacks, connection_state_cb,
+                         BTAV_CONNECTION_STATE_CONNECTING, &(btif_av_cb[index].peer_bda));
+            }
+            else if (bt_av_src_callbacks != NULL)
+            {
+                HAL_CBACK(bt_av_src_callbacks, connection_state_cb,
+                         BTAV_CONNECTION_STATE_CONNECTING, &(btif_av_cb[index].peer_bda));
+            }
             break;
 
         case BTIF_SM_EXIT_EVT:
@@ -491,8 +845,9 @@
 
         case BTA_AV_REJECT_EVT:
             BTIF_TRACE_DEBUG(" Received  BTA_AV_REJECT_EVT ");
-            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
+            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
+                                        &(btif_av_cb[index].peer_bda));
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_IDLE);
             break;
 
         case BTA_AV_OPEN_EVT:
@@ -500,53 +855,114 @@
             tBTA_AV *p_bta_data = (tBTA_AV*)p_data;
             btav_connection_state_t state;
             btif_sm_state_t av_state;
-            BTIF_TRACE_DEBUG("status:%d, edr 0x%x",p_bta_data->open.status,
-                               p_bta_data->open.edr);
+            BTIF_TRACE_DEBUG("status:%d, edr 0x%x, role: 0x%x",p_bta_data->open.status,
+                             p_bta_data->open.edr, p_bta_data->open.role);
 
             if (p_bta_data->open.status == BTA_AV_SUCCESS)
             {
                  state = BTAV_CONNECTION_STATE_CONNECTED;
                  av_state = BTIF_AV_STATE_OPENED;
-                 btif_av_cb.edr = p_bta_data->open.edr;
-
-                 btif_av_cb.peer_sep = p_bta_data->open.sep;
+                 btif_av_cb[index].edr = p_bta_data->open.edr;
+                 if (p_bta_data->open.role == HOST_ROLE_SLAVE)
+                 {
+                    btif_av_cb[index].is_slave = TRUE;
+                 }
+                 btif_av_cb[index].peer_sep = p_bta_data->open.sep;
                  btif_a2dp_set_peer_sep(p_bta_data->open.sep);
+                 if ((p_bta_data->open.edr & BTA_AV_EDR_3MBPS) &&
+                     (!(interop_match_addr(INTEROP_2MBPS_LINK_ONLY,
+                        (const bt_bdaddr_t *)&btif_av_cb[index].peer_bda.address))))
+                 {
+                     BTIF_TRACE_DEBUG("remote supports 3 mbps");
+                     btif_av_cb[index].edr_3mbps = TRUE;
+                 }
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+                 btif_av_cb[index].channel_id = p_bta_data->open.stream_chnl_id;
+                 BTIF_TRACE_DEBUG("streaming channel id updated as : 0x%x",
+                        btif_av_cb[index].channel_id);
+#endif
             }
             else
             {
                 BTIF_TRACE_WARNING("BTA_AV_OPEN_EVT::FAILED status: %d",
                                      p_bta_data->open.status );
+                /* Multicast: Check if connected to AVRC only device
+                 * disconnect when Dual A2DP/Multicast is supported.
+                 */
                 BD_ADDR peer_addr;
                 if ((btif_rc_get_connected_peer(peer_addr))
-                    &&(!bdcmp(btif_av_cb.peer_bda.address, peer_addr)))
+                    &&(!bdcmp(btif_av_cb[index].peer_bda.address, peer_addr)))
                 {
-                    /*
-                     * Disconnect AVRCP connection, if
-                     * A2DP conneciton failed, for any reason
+                    /* Do not disconnect AVRCP connection if A2DP
+                     * connection failed due to SDP failure since remote
+                     * may not support A2DP. In such case we will keep
+                     * AVRCP only connection.
                      */
-                    BTIF_TRACE_WARNING(" Disconnecting AVRCP ");
-                    BTA_AvCloseRc(btif_rc_get_connected_peer_handle());
+                    if (p_bta_data->open.status != BTA_AV_FAIL_SDP)
+                    {
+                        BTIF_TRACE_WARNING("Disconnecting AVRCP ");
+                        BTA_AvCloseRc(btif_rc_get_connected_peer_handle(peer_addr));
+                    }
+                    else
+                    {
+                        BTIF_TRACE_WARNING("Keep AVRCP only connection");
+                    }
                 }
                 state = BTAV_CONNECTION_STATE_DISCONNECTED;
                 av_state  = BTIF_AV_STATE_IDLE;
             }
 
-            /* inform the application of the event */
-            btif_report_connection_state(state, &(btif_av_cb.peer_bda));
-            /* change state to open/idle based on the status */
-            btif_sm_change_state(btif_av_cb.sm_handle, av_state);
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+            if (p_bta_data->open.status != BTA_AV_SUCCESS &&
+                    p_bta_data->open.status != BTA_AV_FAIL_SDP)
             {
-                /* if queued PLAY command,  send it now */
-                btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr,
-                                             (p_bta_data->open.status == BTA_AV_SUCCESS));
+                btif_av_check_and_start_collission_timer(index);
             }
-            else if (btif_av_cb.peer_sep == AVDT_TSEP_SRC)
+
+            /* inform the application of the event */
+            btif_report_connection_state(state, &(btif_av_cb[index].peer_bda));
+            /* change state to open/idle based on the status */
+            btif_sm_change_state(btif_av_cb[index].sm_handle, av_state);
+            /* Check if the other connected AV is playing,
+            * If YES, trigger DUAL Handoff. */
+            if (p_bta_data->open.status == BTA_AV_SUCCESS)
             {
-                /* if queued PLAY command,  send it now */
-                btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr, FALSE);
-                /* Bring up AVRCP connection too */
-                BTA_AvOpenRc(btif_av_cb.bta_handle);
+                /* BTIF AV State updated, now check
+                 * and update multicast state
+                 */
+                btif_av_update_multicast_state(index);
+
+                /*This device should be now ready for all next playbacks*/
+                btif_av_cb[index].current_playing = TRUE;
+                if (enable_multicast == FALSE)
+                {
+                    for (i = 0; i < btif_max_av_clients; i++)
+                    {
+                        //Other device is not current playing
+                        if (i != index)
+                            btif_av_cb[i].current_playing = FALSE;
+                    }
+                    /* In A2dp Multicast, stack will take care of starting
+                     * the stream on newly connected A2dp device. If Handoff
+                     * is supported, trigger Handoff here. */
+                    if (btif_av_is_playing())
+                    {
+                        BTIF_TRACE_DEBUG("Trigger Dual A2dp Handoff on %d", index);
+                        btif_av_trigger_dual_handoff(TRUE, btif_av_cb[index].peer_bda.address);
+                    }
+                }
+                if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
+                {
+                    /* if queued PLAY command,  send it now */
+                    btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr,
+                                (p_bta_data->open.status == BTA_AV_SUCCESS));
+                }
+                else if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC)
+                {
+                    /* if queued PLAY command,  send it now */
+                    btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr, FALSE);
+                    /* Bring up AVRCP connection too */
+                    BTA_AvOpenRc(btif_av_cb[index].bta_handle);
+                }
             }
             btif_queue_advance();
         } break;
@@ -559,16 +975,16 @@
 
             BTIF_TRACE_WARNING("BTIF_AV_SINK_CONFIG_REQ_EVT %d %d", req.sample_rate,
                     req.channel_count);
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC && bt_av_sink_callbacks != NULL) {
-                HAL_CBACK(bt_av_sink_callbacks, audio_config_cb, &(btif_av_cb.peer_bda),
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC && bt_av_sink_callbacks != NULL) {
+                HAL_CBACK(bt_av_sink_callbacks, audio_config_cb, &(btif_av_cb[index].peer_bda),
                         req.sample_rate, req.channel_count);
             }
         } break;
 
         case BTIF_AV_CONNECT_REQ_EVT:
             // Check for device, if same device which moved to opening then ignore callback
-            if (memcmp ((bt_bdaddr_t*)p_data, &(btif_av_cb.peer_bda),
-                sizeof(btif_av_cb.peer_bda)) == 0)
+            if (memcmp ((bt_bdaddr_t*)p_data, &(btif_av_cb[index].peer_bda),
+                sizeof(btif_av_cb[index].peer_bda)) == 0)
             {
                 BTIF_TRACE_DEBUG("%s: Same device moved to Opening state,ignore Connect Req", __func__);
                 btif_queue_advance();
@@ -584,8 +1000,8 @@
 
         case BTA_AV_PENDING_EVT:
             // Check for device, if same device which moved to opening then ignore callback
-            if (memcmp (((tBTA_AV*)p_data)->pend.bd_addr, &(btif_av_cb.peer_bda),
-                sizeof(btif_av_cb.peer_bda)) == 0)
+            if (memcmp (((tBTA_AV*)p_data)->pend.bd_addr, &(btif_av_cb[index].peer_bda),
+                sizeof(btif_av_cb[index].peer_bda)) == 0)
             {
                 BTIF_TRACE_DEBUG("%s: Same device moved to Opening state,ignore Pending Req", __func__);
                 break;
@@ -603,10 +1019,35 @@
             break;
 
         case BTA_AV_CLOSE_EVT:
-            btif_a2dp_on_stopped(NULL);
+            /* avdtp link is closed */
+            /* Check if any other device is playing
+            * and this is not the one.*/
+            if (!btif_av_is_playing())
+            {
+                btif_a2dp_on_stopped(NULL);
+            }
+            /* inform the application that we are disconnected */
             btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
-                    &(btif_av_cb.peer_bda));
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
+                    &(btif_av_cb[index].peer_bda));
+            btif_queue_advance();
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_IDLE);
+            btif_av_check_and_start_collission_timer(index);
+            break;
+
+        case BTIF_AV_DISCONNECT_REQ_EVT:
+            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
+                &(btif_av_cb[index].peer_bda));
+            BTA_AvClose(btif_av_cb[index].bta_handle);
+            btif_queue_advance();
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_IDLE);
+            break;
+
+        case BTA_AV_RC_OPEN_EVT:
+             btif_rc_handler(event, p_data);;
+            break;
+
+        case BTA_AV_RC_COLL_DETECTED_EVT:
+            BTIF_TRACE_WARNING("BTA_AV_RC_COLL_DETECTED_EVT: Not Starting conn retry timer");
             break;
 
         CHECK_RC_EVENT(event, p_data);
@@ -631,21 +1072,42 @@
 **
 *******************************************************************************/
 
-static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *p_data)
+static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *p_data, int index)
 {
-    BTIF_TRACE_DEBUG("%s event:%s flags %x", __FUNCTION__,
-                     dump_av_sm_event_name(event), btif_av_cb.flags);
+    BTIF_TRACE_IMP("%s event:%s flags %x and index = %d", __FUNCTION__,
+                     dump_av_sm_event_name(event), btif_av_cb[index].flags, index);
 
     switch (event)
     {
         case BTIF_SM_ENTER_EVT:
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
             {
-                /* immediately stop transmission of frames */
-                btif_a2dp_set_tx_flush(TRUE);
-                /* wait for audioflinger to stop a2dp */
+                /* Multicast/Soft Hand-off:
+                 * If MC/SHO is enabled we need to keep/start playing on
+                 * other device.
+                 */
+                if (btif_av_is_connected_on_other_idx(index))
+                {
+                    if (btif_av_is_playing())
+                    {
+                        APPL_TRACE_DEBUG("Keep playing on other device");
+                    }
+                    else
+                    {
+                        APPL_TRACE_DEBUG("Not playing on other devie: Set Flush");
+                        btif_a2dp_set_tx_flush(TRUE);
+                    }
+                }
+                else
+                {
+                    /* Single connections scenario:
+                     * Immediately stop transmission of frames
+                     * wait for audioflinger to stop a2dp
+                     */
+                    btif_a2dp_set_tx_flush(TRUE);
+                }
             }
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC)
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC)
             {
                 btif_a2dp_set_rx_flush(TRUE);
             }
@@ -653,17 +1115,35 @@
 
         case BTA_AV_STOP_EVT:
         case BTIF_AV_STOP_STREAM_REQ_EVT:
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
             {
-              /* immediately flush any pending tx frames while suspend is pending */
-              btif_a2dp_set_tx_flush(TRUE);
+                /* Dont stop in DUAL A2dp connections, as
+                * UIPC will keep waiting for Audio CTRL channel
+                * to get closed which is not required in Dual A2dp.
+                * We will stop only when only single A2dp conn is present.*/
+                if (btif_av_is_connected_on_other_idx(index))
+                {
+                    if (!btif_av_is_playing())
+                    {
+                        APPL_TRACE_WARNING("Suspend the AV Data channel");
+                        //Flush and close media channel
+                        btif_a2dp_set_tx_flush(TRUE);
+                        btif_media_task_stop_aa_req();
+                    }
+                }
+                else
+                {
+                    /* immediately flush any pending tx frames while suspend is pending */
+                    APPL_TRACE_WARNING("Stop the AV Data channel");
+                    btif_a2dp_set_tx_flush(TRUE);
+                    btif_a2dp_on_stopped(NULL);
+                }
             }
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC)
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC)
             {
                 btif_a2dp_set_rx_flush(TRUE);
+                btif_a2dp_on_stopped(NULL);
             }
-
-            btif_a2dp_on_stopped(NULL);
             break;
 
         case BTIF_SM_EXIT_EVT:
@@ -672,9 +1152,9 @@
         case BTA_AV_CLOSE_EVT:
 
             /* inform the application that we are disconnecting */
-            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
+            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb[index].peer_bda));
 
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_IDLE);
             break;
 
         /* Handle the RC_CLOSE event for the cleanup */
@@ -682,6 +1162,10 @@
             btif_rc_handler(event, (tBTA_AV*)p_data);
             break;
 
+        case BTA_AV_RC_COLL_DETECTED_EVT:
+            BTIF_TRACE_WARNING("BTA_AV_RC_COLL_DETECTED_EVT: Not Starting conn retry timer");
+            break;
+
         case BTIF_AV_OFFLOAD_START_REQ_EVT:
             btif_a2dp_on_offload_started(BTA_AV_FAIL);
             BTIF_TRACE_ERROR("BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started Closing");
@@ -695,6 +1179,19 @@
    return TRUE;
 }
 
+/******************************************************************************
+**
+** Function        btif_av_is_offload_supported
+**
+** Description     Returns split mode status
+**
+** Returns         TRUE if split mode is enabled, FALSE otherwise
+********************************************************************************/
+BOOLEAN btif_av_is_offload_supported()
+{
+    return bt_split_a2dp_enabled;
+}
+
 /*****************************************************************************
 **
 ** Function     btif_av_state_opened_handler
@@ -705,131 +1202,279 @@
 **
 *******************************************************************************/
 
-static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
+static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data, int index)
 {
     tBTA_AV *p_av = (tBTA_AV*)p_data;
 
-    BTIF_TRACE_DEBUG("%s event:%s flags %x", __FUNCTION__,
-                     dump_av_sm_event_name(event), btif_av_cb.flags);
+    BTIF_TRACE_IMP("%s event:%s flags %x and index = %d", __FUNCTION__,
+                     dump_av_sm_event_name(event), btif_av_cb[index].flags, index);
 
-    if ( (event == BTA_AV_REMOTE_CMD_EVT) && (btif_av_cb.flags & BTIF_AV_FLAG_REMOTE_SUSPEND) &&
+    if ((event == BTA_AV_REMOTE_CMD_EVT) &&
          (p_av->remote_cmd.rc_id == BTA_AV_RC_PLAY) )
     {
-        BTIF_TRACE_EVENT("%s: Resetting remote suspend flag on RC PLAY", __FUNCTION__);
-        btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
+        if (btif_av_check_flag_remote_suspend(index))
+        {
+            BTIF_TRACE_EVENT("%s: Resetting remote suspend flag on RC PLAY",
+                __FUNCTION__);
+            btif_av_clear_remote_suspend_flag();
+            if (btif_av_is_offload_supported())
+            {
+                btif_dispatch_sm_event(BTIF_AV_START_STREAM_REQ_EVT, NULL, 0);
+            }
+        }
     }
 
     switch (event)
     {
         case BTIF_SM_ENTER_EVT:
-            btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_STOP;
-            btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
+            btif_av_cb[index].flags &= ~BTIF_AV_FLAG_PENDING_STOP;
+            btif_av_cb[index].flags &= ~BTIF_AV_FLAG_PENDING_START;
             break;
 
         case BTIF_SM_EXIT_EVT:
-            btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
             break;
 
         case BTIF_AV_START_STREAM_REQ_EVT:
-            if (btif_av_cb.peer_sep != AVDT_TSEP_SRC)
-                btif_a2dp_setup_codec();
-            BTA_AvStart();
-            btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_START;
+            /* update multicast state here if new device is connected
+             * after A2dp connection. New A2dp device is connected
+             * whlie playing */
+            btif_av_update_multicast_state(index);
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC)
+            {
+                BTA_AvStart(btif_av_cb[index].bta_handle);
+                btif_av_cb[index].flags |= BTIF_AV_FLAG_PENDING_START;
+                break;
+            }
+            tBTIF_STATUS status = btif_a2dp_setup_codec(btif_av_cb[index].bta_handle);
+            if (status == BTIF_SUCCESS)
+            {
+                int idx = 0;
+                BTA_AvStart(btif_av_cb[index].bta_handle);
+                if (enable_multicast == TRUE)
+                {
+                    /* In A2dp Multicast, DUT initiated stream request
+                    * should be true for all connected A2dp devices. */
+                    for (; idx < btif_max_av_clients; idx++)
+                    {
+                        btif_av_cb[idx].flags |= BTIF_AV_FLAG_PENDING_START;
+                    }
+                }
+                else
+                {
+                    btif_av_cb[index].flags |= BTIF_AV_FLAG_PENDING_START;
+                }
+            }
+            else if (status == BTIF_ERROR_SRV_AV_CP_NOT_SUPPORTED)
+            {
+#if defined(BTA_AV_DISCONNECT_IF_NO_SCMS_T) && (BTA_AV_DISCONNECT_IF_NO_SCMS_T == TRUE)
+                BTIF_TRACE_ERROR0("SCMST enabled, disconnect as remote does not support SCMST");
+                BTA_AvDisconnect(btif_av_cb[index].peer_bda.address);
+#else
+                BTIF_TRACE_WARNING("SCMST enabled, connecting to non SCMST SEP");
+                BTA_AvStart(btif_av_cb[index].bta_handle);
+                btif_av_cb[index].flags |= BTIF_AV_FLAG_PENDING_START;
+#endif
+            }
+            else
+            {
+                BTIF_TRACE_ERROR("## AV Disconnect## status : %x",status);
+                BTA_AvDisconnect(btif_av_cb[index].peer_bda.address);
+            }
+            break;
+
+        case BTIF_AV_UPDATE_ENCODER_REQ_EVT:
+            btif_a2dp_update_codec();
             break;
 
         case BTA_AV_START_EVT:
         {
-            BTIF_TRACE_EVENT("BTA_AV_START_EVT status %d, suspending %d, init %d",
+            BTIF_TRACE_DEBUG("BTA_AV_START_EVT status %d, suspending %d, init %d",
                 p_av->start.status, p_av->start.suspending, p_av->start.initiator);
+            BTIF_TRACE_DEBUG("BTA_AV_START_EVT role: %d", p_av->start.role);
+            if (p_av->start.role == HOST_ROLE_SLAVE)
+            {
+                btif_av_cb[index].is_slave = TRUE;
+            }
+            else
+            {
+                // update if we are master after role switch before start
+                btif_av_cb[index].is_slave = FALSE;
+            }
+            /* There can be role switch after device is connected,
+             * hence check for role before starting multicast, and
+             * disable if we are in slave role for any connection
+             */
+            btif_av_update_multicast_state(index);
 
             if ((p_av->start.status == BTA_SUCCESS) && (p_av->start.suspending == TRUE))
                 return TRUE;
 
+            /* if remote tries to start a2dp when call is in progress, suspend it right away */
+            if ((!(btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START)) && (!btif_hf_is_call_vr_idle())) {
+                BTIF_TRACE_EVENT("%s: trigger suspend as call is in progress!!", __FUNCTION__);
+                btif_av_cb[index].flags &= ~BTIF_AV_FLAG_PENDING_START;
+                btif_av_cb[index].is_remote_start_received = TRUE;
+                btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_STARTED);
+                btif_dispatch_sm_event(BTIF_AV_REMOTE_SUSPEND_STREAM_REQ_EVT, NULL, 0);
+                break;
+            }
+
             /* if remote tries to start a2dp when DUT is a2dp source
              * then suspend. In case a2dp is sink and call is active
              * then disconnect the AVDTP channel
              */
-            if (!(btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START))
+            if (!(btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START))
             {
-                if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+                if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
                 {
-                    BTIF_TRACE_EVENT("%s: trigger suspend as remote initiated!!", __FUNCTION__);
-                    btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
-                }
-            }
+                    if (enable_multicast)
+                    {
+                        /* Stack will start the playback on newly connected
+                         * A2dp device, if the playback is already happening on
+                         * other connected device.*/
+                        if (btif_av_is_playing())
+                        {
+                            /* when HS2 is connected during HS1 playing, stack directly
+                             * sends start event hence update encoder so that least L2CAP
+                             *  MTU is selected.*/
+                            //btif_a2dp_update_codec();
+                            BTIF_TRACE_DEBUG("%s: A2dp Multicast playback",
+                                    __FUNCTION__);
+                        }
+                        /* initiate suspend if start is initiate by remote and multicast
+                         * is enabled.
+                         * Avoid suspend if stream is started as quick suspend-start
+                         * creates IOT issue, seen with SBH50.
+                         */
 
-            /*  In case peer is A2DP SRC we do not want to ack commands on UIPC*/
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
-            {
-                if (btif_a2dp_on_started(&p_av->start,
-                    ((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) != 0)))
-                {
-                    /* only clear pending flag after acknowledgement */
-                    btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
+                        if (!p_av->start.initiator && !btif_av_is_playing())
+                        {
+                            BTIF_TRACE_DEBUG("initiate suspend for remote start");
+                            btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
+                        }
+                    }
+                    else
+                    {
+                        if ((btif_av_cb[index].flags & BTIF_AV_FLAG_REMOTE_SUSPEND))
+                        {
+                            BTIF_TRACE_DEBUG("%s: clear remote suspend flag on remote start",
+                                __FUNCTION__);
+                            btif_av_cb[index].flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
+                            if (btif_av_is_offload_supported())
+                            {
+                               btif_media_start_vendor_command();
+                            }
+                        }
+                        else
+                        {
+                            BTIF_TRACE_DEBUG("%s: honor remote started for BL device",__FUNCTION__);
+                            btif_a2dp_on_remote_started();
+                            btif_av_cb[index].is_remote_start_received = TRUE;
+                        }
+                    }
                 }
             }
 
             /* remain in open state if status failed */
+            /* Multicast-soft Handoff:
+             * START failed, cleanup Handoff flag.
+             */
             if (p_av->start.status != BTA_AV_SUCCESS)
-                return FALSE;
+            {
+                int i;
 
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC)
+                /* In case peer is A2DP SRC we do not want to ack commands on UIPC */
+                if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
+                {
+                    if (btif_a2dp_on_started(&p_av->start,
+                        ((btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START) != 0),
+                        btif_av_cb[index].bta_handle))
+                    {
+                        /* only clear pending flag after acknowledgement */
+                        btif_av_cb[index].flags &= ~BTIF_AV_FLAG_PENDING_START;
+                    }
+                }
+                /* Clear dual handoff flag */
+                for (i = 0; i < btif_max_av_clients; i++)
+                {
+                    btif_av_cb[i].dual_handoff = FALSE;
+                }
+                return FALSE;
+            }
+
+#ifndef AVK_BACKPORT
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC)
             {
                 btif_a2dp_set_rx_flush(FALSE); /*  remove flush state, ready for streaming*/
             }
+#endif
 
-            /* change state to started, send acknowledgement if start is pending */
-            if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
-                if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
-                    btif_a2dp_on_started(NULL, TRUE);
-                /* pending start flag will be cleared when exit current state */
-            }
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_STARTED);
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_STARTED);
 
         } break;
 
         case BTIF_AV_DISCONNECT_REQ_EVT:
-            BTA_AvClose(btif_av_cb.bta_handle);
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
-                BTA_AvCloseRc(btif_av_cb.bta_handle);
+            BTA_AvClose(btif_av_cb[index].bta_handle);
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC) {
+                BTA_AvCloseRc(btif_av_cb[index].bta_handle);
             }
 
             /* inform the application that we are disconnecting */
-            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb.peer_bda));
+            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb[index].peer_bda));
             break;
 
         case BTA_AV_CLOSE_EVT:
              /* avdtp link is closed */
-            btif_a2dp_on_stopped(NULL);
+             /*Dont close the A2dp when Dual playback is happening*/
+             if (btif_av_is_connected_on_other_idx(index))
+             {
+                 APPL_TRACE_WARNING("Conn is closing,close AV data channel");
+                 if (!btif_av_is_playing())
+                 {
+                     APPL_TRACE_WARNING("Suspend the AV Data channel");
+                     /* ensure tx frames are immediately suspended */
+                     btif_a2dp_set_tx_flush(TRUE);
+                     btif_media_task_stop_aa_req();
+                 }
+             }
+             else
+             {
+                 APPL_TRACE_WARNING("Stop the AV Data channel");
+                 btif_a2dp_on_stopped(NULL);
+             }
 
+            btif_av_cb[index].flags |= BTIF_AV_FLAG_PENDING_DISCONNECT;
             /* inform the application that we are disconnected */
-            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
+            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
+                                        &(btif_av_cb[index].peer_bda));
+            btif_av_cb[index].flags &= ~BTIF_AV_FLAG_PENDING_DISCONNECT;
 
             /* change state to idle, send acknowledgement if start is pending */
-            if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
+            if (btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START) {
                 btif_a2dp_ack_fail();
-                /* pending start flag will be cleared when exit current state */
+                btif_av_cb[index].flags &= ~BTIF_AV_FLAG_PENDING_START;
             }
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
+
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_IDLE);
             break;
 
         case BTA_AV_RECONFIG_EVT:
-            if((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) &&
+            if((btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START) &&
                 (p_av->reconfig.status == BTA_AV_SUCCESS))
             {
                APPL_TRACE_WARNING("reconfig done BTA_AVstart()");
-               BTA_AvStart();
+               BTA_AvStart(btif_av_cb[index].bta_handle);
             }
-            else if(btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START)
+            else if(btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START)
             {
-               btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
+               btif_av_cb[index].flags &= ~BTIF_AV_FLAG_PENDING_START;
                btif_a2dp_ack_fail();
             }
             break;
 
         case BTIF_AV_CONNECT_REQ_EVT:
-            if (memcmp ((bt_bdaddr_t*)p_data, &(btif_av_cb.peer_bda),
-                sizeof(btif_av_cb.peer_bda)) == 0)
+            if (memcmp ((bt_bdaddr_t*)p_data, &(btif_av_cb[index].peer_bda),
+                sizeof(btif_av_cb[index].peer_bda)) == 0)
             {
                 BTIF_TRACE_DEBUG("%s: Ignore BTIF_AV_CONNECT_REQ_EVT for same device", __func__);
             }
@@ -847,6 +1492,15 @@
             BTIF_TRACE_ERROR("BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started Opened");
             break;
 
+        case BTA_AV_RC_OPEN_EVT:
+            btif_av_check_rc_connection_priority(p_data);
+            break;
+
+        case BTA_AV_RC_COLL_DETECTED_EVT:
+            BTIF_TRACE_ERROR("BTA_AV_RC_COLL_DETECTED_EVT: Start conn retry timer");
+            btif_av_check_and_start_collission_timer(index);
+            break;
+
         CHECK_RC_EVENT(event, p_data);
 
         default:
@@ -868,31 +1522,84 @@
 **
 *******************************************************************************/
 
-static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data)
+static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data, int index)
 {
     tBTA_AV *p_av = (tBTA_AV*)p_data;
+    btif_sm_state_t state = BTIF_AV_STATE_IDLE;
+    int i;
+    BOOLEAN hal_suspend_pending = FALSE;
 
-    BTIF_TRACE_DEBUG("%s event:%s flags %x", __FUNCTION__,
-                     dump_av_sm_event_name(event), btif_av_cb.flags);
+    BTIF_TRACE_IMP("%s event:%s flags %x  index =%d", __FUNCTION__,
+                     dump_av_sm_event_name(event), btif_av_cb[index].flags, index);
 
     switch (event)
     {
         case BTIF_SM_ENTER_EVT:
+            /*Ack from entry point of started handler instead of open state to avoid race condition*/
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
+            {
+                if (!((!enable_multicast)&&((btif_av_cb[index].is_remote_start_received)
+                && ((btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START) == 0))))
+                {
+                    BTIF_TRACE_IMP("%s update media task on DUT initiated start for index =%d",
+                        __FUNCTION__, index);
+                    if (btif_a2dp_on_started(&p_av->start,
+                        ((btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START) != 0),
+                          btif_av_cb[index].bta_handle))
+                    {
+                        /* only clear pending flag after acknowledgement */
+                        btif_av_cb[index].flags &= ~BTIF_AV_FLAG_PENDING_START;
+                    }
+                }
+                else
+                {
+                    BTIF_TRACE_IMP("%s Do not update media task on remote start for index =%d",
+                        __FUNCTION__, index);
+                }
+            }
+
+            /* Already changed state to started, send acknowledgement if start is pending */
+            if (btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START) {
+                if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
+                    btif_a2dp_on_started(NULL, TRUE, btif_av_cb[index].bta_handle);
+                btif_av_cb[index].flags &= ~BTIF_AV_FLAG_PENDING_START;
+            }
 
             /* we are again in started state, clear any remote suspend flags */
-            btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
+            btif_av_cb[index].flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
 
-            /**
-             * Report to components above that we have entered the streaming
-             * stage, this should usually be followed by focus grant.
-             * see update_audio_focus_state()
-             */
-            btif_report_audio_state(BTAV_AUDIO_STATE_STARTED, &(btif_av_cb.peer_bda));
+            if ((!enable_multicast)&&((btif_av_cb[index].is_remote_start_received)
+            && (btif_av_is_playing_on_other_idx(index))))
+            {
+                BTIF_TRACE_IMP("%s Do not update audio state change to app for index =%d",
+                    __FUNCTION__, index);
+            }
+            else
+            {
+                btif_report_audio_state(BTAV_AUDIO_STATE_STARTED, &(btif_av_cb[index].peer_bda));
+            }
+            btif_av_cb[index].is_device_playing = TRUE;
 
             /* increase the a2dp consumer task priority temporarily when start
             ** audio playing, to avoid overflow the audio packet queue. */
             adjust_priority_a2dp(TRUE);
-
+#ifdef AVK_BACKPORT
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC)
+            {
+                btif_av_request_audio_focus(TRUE);
+            }
+#endif
+            //Clear Dual Handoff for all SCBs
+            for (i = 0; i < btif_max_av_clients; i++)
+            {
+                btif_av_cb[i].dual_handoff = FALSE;
+                //Other device is not current playing
+                if (i != index)
+                    btif_av_cb[i].current_playing = FALSE;
+            }
+            //This is latest device to play now
+            btif_av_cb[index].current_playing = TRUE;
+            //reconfig_a2dp = FALSE;
             break;
 
         case BTIF_SM_EXIT_EVT:
@@ -903,8 +1610,25 @@
 
         case BTIF_AV_START_STREAM_REQ_EVT:
             /* we were remotely started, just ack back the local request */
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
-                btif_a2dp_on_started(NULL, TRUE);
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
+            {
+                btif_a2dp_on_started(NULL, TRUE, btif_av_cb[index].bta_handle);
+                btif_report_audio_state(BTAV_AUDIO_STATE_STARTED, &(btif_av_cb[index].peer_bda));
+                btif_av_cb[index].is_device_playing = TRUE;
+                for (i = 0; i < btif_max_av_clients; i++)
+                {
+                    //Other device is not current playing
+                    if (i != index)
+                        btif_av_cb[i].current_playing = FALSE;
+                }
+                //This is latest device to play now
+                btif_av_cb[index].current_playing = TRUE;
+                btif_av_reset_reconfig_flag();
+            }
+            break;
+
+        case BTIF_AV_UPDATE_ENCODER_REQ_EVT:
+            btif_a2dp_update_codec();
             break;
 
         /* fixme -- use suspend = true always to work around issue with BTA AV */
@@ -912,56 +1636,150 @@
         case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
 
             /* set pending flag to ensure btif task is not trying to restart
-               stream while suspend is in progress */
-            btif_av_cb.flags |= BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
+             * stream while suspend is in progress.
+             * Multicast: If streaming is happening on both devices, we need
+             * to update flag for both connections as SUSPEND request will
+             * be sent to only one stream as internally BTA takes care of
+             * suspending both streams.
+             */
+            if (enable_multicast)
+            {
+                for(i = 0; i < btif_max_av_clients; i++)
+                {
+                    state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+                    if (state == BTIF_AV_STATE_STARTED)
+                    {
+                        btif_av_cb[i].flags |= BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
+                    }
+                }
+            }
+            else
+            {
+                btif_av_cb[index].flags |= BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
+            }
 
             /* if we were remotely suspended but suspend locally, local suspend
                always overrides */
-            btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
+            btif_av_cb[index].flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
 
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
             {
             /* immediately stop transmission of frames while suspend is pending */
                 btif_a2dp_set_tx_flush(TRUE);
             }
 
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC) {
                 btif_a2dp_set_rx_flush(TRUE);
                 btif_a2dp_on_stopped(NULL);
             }
 
-            BTA_AvStop(TRUE);
+            BTA_AvStop(TRUE, btif_av_cb[index].bta_handle);
             break;
 
         case BTIF_AV_DISCONNECT_REQ_EVT:
 
+            //Now it is not the current playing
+            btif_av_cb[index].current_playing = FALSE;
+            btif_av_update_current_playing_device(index);
+            btif_rc_clear_priority(btif_av_cb[index].peer_bda.address);
+            if (bt_split_a2dp_enabled && btif_av_is_connected_on_other_idx(index))
+            {
+               /*Fake handoff state to switch streaming to other coddeced
+                  device */
+                btif_av_cb[index].dual_handoff = TRUE;
+            }
             /* request avdtp to close */
-            BTA_AvClose(btif_av_cb.bta_handle);
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
-                BTA_AvCloseRc(btif_av_cb.bta_handle);
+            BTA_AvClose(btif_av_cb[index].bta_handle);
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC) {
+                BTA_AvCloseRc(btif_av_cb[index].bta_handle);
             }
 
             /* inform the application that we are disconnecting */
-            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb.peer_bda));
+            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb[index].peer_bda));
 
             /* wait in closing state until fully closed */
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_CLOSING);
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_CLOSING);
+            if (bt_split_a2dp_enabled &&
+                btif_av_is_connected_on_other_idx(index))
+            {
+                BTIF_TRACE_DEBUG("%s: Notify framework to reconfig",__func__);
+                int idx = btif_av_get_other_connected_idx(index);
+                /* Fix for below Klockwork Issue
+                 * Array 'btif_av_cb' of size 2 may use index value(s) -1 */
+                if (idx != INVALID_INDEX)
+                {
+                    reconfig_a2dp = TRUE;
+                    HAL_CBACK(bt_av_src_callbacks, reconfig_a2dp_trigger_cb, 1,
+                                                    &(btif_av_cb[idx].peer_bda));
+                }
+            }
             break;
 
         case BTA_AV_SUSPEND_EVT:
-
             BTIF_TRACE_EVENT("BTA_AV_SUSPEND_EVT status %d, init %d",
                  p_av->suspend.status, p_av->suspend.initiator);
+            //Check if this suspend is due to DUAL_Handoff
+            if ((btif_av_cb[index].dual_handoff) &&
+                (p_av->suspend.status == BTA_AV_SUCCESS))
+            {
+                BTIF_TRACE_EVENT("BTA_AV_SUSPEND_EVT: Dual handoff");
+                btif_dispatch_sm_event(BTIF_AV_START_STREAM_REQ_EVT, NULL, 0);
+            }
+            if (p_av->suspend.initiator != TRUE)
+            {
+                /* remote suspend, notify HAL and await audioflinger to
+                 * suspend/stop stream
+                 * set remote suspend flag to block media task from restarting
+                 * stream only if we did not already initiate a local suspend
+                 * set remote suspend flag before suspending stream as in race conditions
+                 * when stream is suspended, but flag is things ge tossed up
+                 */
+                BTIF_TRACE_EVENT("Clear before suspending");
+                if ((btif_av_cb[index].flags & BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING) == 0)
+                    btif_av_cb[index].flags |= BTIF_AV_FLAG_REMOTE_SUSPEND;
+                for (int i = 0; i < btif_max_av_clients; i++)
+                {
+                    if ((i != index) && btif_av_get_ongoing_multicast())
+                    {
+                        multicast_disabled = TRUE;
+                        btif_av_update_multicast_state(index);
+                        BTIF_TRACE_EVENT("Initiate suspend for other HS also");
+                        btif_sm_dispatch(btif_av_cb[i].sm_handle,
+                                BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL);
+                    }
+                }
+            }
 
             /* a2dp suspended, stop media task until resumed */
-            btif_a2dp_on_suspended(&p_av->suspend);
+            /* Multicast: If streaming on other device, don't call onsuspended
+             * as it unblocks the audio process and audio process may send
+             * subsequent commands and create problem during the time where we
+             * still did not receive response for SUSPEND sent to other device.
+             * Keep the suspend failure handling untouched and handle
+             * only success case to check and avoid calling onsuspended.
+             */
+            if (btif_a2dp_get_pending_hal_command() == A2DP_CTRL_CMD_SUSPEND ||
+                btif_a2dp_get_pending_hal_command() == A2DP_CTRL_CMD_STOP)
+            {
+                BTIF_TRACE_DEBUG("HAL suspend/stop pending ack the suspend");
+                hal_suspend_pending = TRUE;
+            }
+            if ((p_av->suspend.status != BTA_AV_SUCCESS) ||
+                hal_suspend_pending || !btif_av_is_playing_on_other_idx(index))
+            {
+                btif_a2dp_on_suspended(&p_av->suspend);
+            }
+            else if(btif_av_is_playing_on_other_idx(index))
+            {
+                BTIF_TRACE_DEBUG("Other device not suspended, don't ack the suspend");
+            }
 
             /* if not successful, remain in current state */
             if (p_av->suspend.status != BTA_AV_SUCCESS)
             {
-                btif_av_cb.flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
+                btif_av_cb[index].flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
 
-               if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+               if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
                {
                 /* suspend failed, reset back tx flush state */
                     btif_a2dp_set_tx_flush(FALSE);
@@ -969,64 +1787,114 @@
                 return FALSE;
             }
 
-            if (p_av->suspend.initiator != TRUE)
+            if ((!enable_multicast)&& btif_av_cb[index].is_suspend_for_remote_start
+            && (btif_av_is_playing_on_other_idx(index)))
             {
-                /* remote suspend, notify HAL and await audioflinger to
-                   suspend/stop stream */
-
-                /* set remote suspend flag to block media task from restarting
-                   stream only if we did not already initiate a local suspend */
-                if ((btif_av_cb.flags & BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING) == 0)
-                    btif_av_cb.flags |= BTIF_AV_FLAG_REMOTE_SUSPEND;
-
-                btif_report_audio_state(BTAV_AUDIO_STATE_REMOTE_SUSPEND, &(btif_av_cb.peer_bda));
+                BTIF_TRACE_IMP("%s Do not update audio state change to app for index =%d",
+                    __FUNCTION__, index);
             }
             else
             {
-                btif_report_audio_state(BTAV_AUDIO_STATE_STOPPED, &(btif_av_cb.peer_bda));
+                btif_report_audio_state(BTAV_AUDIO_STATE_REMOTE_SUSPEND, &(btif_av_cb[index].peer_bda));
             }
+            btif_av_cb[index].is_suspend_for_remote_start = FALSE;
 
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED);
+            btif_av_cb[index].is_device_playing = FALSE;
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_OPENED);
 
             /* suspend completed and state changed, clear pending status */
-            btif_av_cb.flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
+            btif_av_cb[index].flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
             break;
 
         case BTA_AV_STOP_EVT:
 
-            btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
-            btif_a2dp_on_stopped(&p_av->suspend);
+            btif_av_cb[index].flags |= BTIF_AV_FLAG_PENDING_STOP;
+            btif_av_cb[index].current_playing = FALSE;
+            if (btif_av_is_connected_on_other_idx(index))
+            {
+                if (enable_multicast == FALSE)
+                {
+                    APPL_TRACE_WARNING("other Idx is connected, move to SUSPENDED");
+                    if (!bt_split_a2dp_enabled) {
+                        btif_rc_send_pause_command();
+                    }
+                    btif_a2dp_on_stopped(&p_av->suspend);
+                }
+            }
+            else
+            {
+                APPL_TRACE_WARNING("Stop the AV Data channel as no connection is present");
+                btif_a2dp_on_stopped(&p_av->suspend);
+            }
+            btif_av_cb[index].is_device_playing = FALSE;
 
-            btif_report_audio_state(BTAV_AUDIO_STATE_STOPPED, &(btif_av_cb.peer_bda));
-
+            if ((!enable_multicast)&& btif_av_cb[index].is_suspend_for_remote_start
+            && (btif_av_is_playing_on_other_idx(index)))
+            {
+                BTIF_TRACE_IMP("%s Do not update audio state change to app for index =%d",
+                    __FUNCTION__, index);
+            }
+            else
+            {
+                btif_report_audio_state(BTAV_AUDIO_STATE_STOPPED, &(btif_av_cb[index].peer_bda));
+            }
+            btif_av_cb[index].is_suspend_for_remote_start = FALSE;
             /* if stop was successful, change state to open */
             if (p_av->suspend.status == BTA_AV_SUCCESS)
-                btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED);
+                btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_OPENED);
+
+            if (bt_split_a2dp_enabled &&
+                btif_av_is_connected_on_other_idx(index))
+            {
+               /*Fake handoff state to switch streaming to other coddeced
+                  device */
+                btif_av_cb[index].dual_handoff = TRUE;
+                BTIF_TRACE_DEBUG("%s: Notify framework to reconfig",__func__);
+                int idx = btif_av_get_other_connected_idx(index);
+                /* Fix for below Klockwork Issue
+                 * Array 'btif_av_cb' of size 2 may use index value(s) -1 */
+                if (idx != INVALID_INDEX)
+                {
+                    reconfig_a2dp = TRUE;
+                    HAL_CBACK(bt_av_src_callbacks, reconfig_a2dp_trigger_cb, 1,
+                                                    &(btif_av_cb[idx].peer_bda));
+                }
+            }
 
             break;
 
         case BTA_AV_CLOSE_EVT:
 
-             btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
+             btif_av_cb[index].flags |= BTIF_AV_FLAG_PENDING_STOP;
 
             /* avdtp link is closed */
+            APPL_TRACE_WARNING("Stop the AV Data channel");
             btif_a2dp_on_stopped(NULL);
 
             /* inform the application that we are disconnected */
-            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
+            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
+                                        &(btif_av_cb[index].peer_bda));
 
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_IDLE);
+            break;
+
+        case BTA_AV_RC_OPEN_EVT:
+            btif_av_check_rc_connection_priority(p_data);
             break;
 
         case BTIF_AV_OFFLOAD_START_REQ_EVT:
-            BTA_AvOffloadStart(btif_av_cb.bta_handle);
+            BTA_AvOffloadStart(btif_av_cb[index].bta_handle);
             break;
 
         case BTA_AV_OFFLOAD_START_RSP_EVT:
-
             btif_a2dp_on_offload_started(p_av->status);
             break;
 
+        case BTA_AV_RC_COLL_DETECTED_EVT:
+            BTIF_TRACE_ERROR("BTA_AV_RC_COLL_DETECTED_EVT: Start conn retry timer");
+            btif_av_check_and_start_collission_timer(index);
+            break;
+
         CHECK_RC_EVENT(event, p_data);
 
         default:
@@ -1038,33 +1906,6 @@
     return TRUE;
 }
 
-/*****************************************************************************
-**  Local event handlers
-******************************************************************************/
-
-static void btif_av_handle_event(UINT16 event, char* p_param)
-{
-    BTIF_TRACE_EVENT("%s event:%s", __func__,
-                     dump_av_sm_event_name((btif_av_sm_event_t)event));
-    switch(event)
-    {
-        case BTIF_AV_CLEANUP_REQ_EVT:
-            btif_a2dp_stop_media_task();
-            break;
-
-        case BTA_AV_REGISTER_EVT:
-            if (btif_av_cb.sm_handle == NULL)
-            {
-                btif_av_cb.bta_handle = ((tBTA_AV*)p_param)->registr.hndl;
-                BTIF_TRACE_DEBUG("%s: BTA AV Handle updated", __func__);
-            }
-            /* FALLTHROUGH */
-        default:
-            btif_sm_dispatch(btif_av_cb.sm_handle, event, (void*)p_param);
-            btif_av_event_free_data(event, p_param);
-    }
-}
-
 void btif_av_event_deep_copy(UINT16 event, char *p_dest, char *p_src)
 {
     tBTA_AV *av_src = (tBTA_AV *)p_src;
@@ -1100,6 +1941,25 @@
                 }
             }
             break;
+        case BTA_AV_BROWSE_MSG_EVT:
+            if (av_src->browse_msg.p_msg)
+            {
+                av_dest->browse_msg.p_msg = osi_calloc(sizeof(tAVRC_MSG));
+                assert(av_dest->browse_msg.p_msg);
+                memcpy(av_dest->browse_msg.p_msg, av_src->browse_msg.p_msg, sizeof(tAVRC_MSG));
+
+                if (av_src->browse_msg.p_msg->browse.p_browse_data &&
+                    av_src->browse_msg.p_msg->browse.browse_len)
+                {
+                    av_dest->browse_msg.p_msg->browse.p_browse_data = osi_calloc(
+                        av_src->browse_msg.p_msg->browse.browse_len);
+                    assert(av_dest->browse_msg.p_msg->browse.p_browse_data);
+                    memcpy(av_dest->browse_msg.p_msg->browse.p_browse_data,
+                        av_src->browse_msg.p_msg->browse.p_browse_data,
+                        av_src->browse_msg.p_msg->browse.browse_len);
+                }
+            }
+            break;
 
         default:
             break;
@@ -1121,18 +1981,547 @@
                 }
             }
             break;
+        case BTA_AV_BROWSE_MSG_EVT:
+            {
+                tBTA_AV *av = (tBTA_AV*)p_data;
+
+                if (av->browse_msg.p_msg)
+                {
+                    if (av->browse_msg.p_msg->browse.p_browse_data)
+                        osi_free(av->browse_msg.p_msg->browse.p_browse_data);
+                    osi_free(av->browse_msg.p_msg);
+                }
+            }
+            break;
 
         default:
             break;
     }
 }
 
+/*****************************************************************************
+**  Local event handlers
+******************************************************************************/
+
+static void btif_av_handle_event(UINT16 event, char* p_param)
+{
+    int index = 0;
+    tBTA_AV *p_bta_data = (tBTA_AV*)p_param;
+    bt_bdaddr_t * bt_addr;
+    UINT8 role;
+    int uuid;
+
+    switch (event)
+    {
+        case BTIF_AV_INIT_REQ_EVT:
+            BTIF_TRACE_IMP("%s: BTIF_AV_INIT_REQ_EVT", __FUNCTION__);
+            if(btif_a2dp_start_media_task())
+                btif_a2dp_on_init();
+            break;
+        /*events from Upper layer and Media Task*/
+        case BTIF_AV_CLEANUP_REQ_EVT: /*Clean up to be called on default index*/
+            BTIF_TRACE_IMP("%s: BTIF_AV_CLEANUP_REQ_EVT", __FUNCTION__);
+            uuid = (int)*p_param;
+            if (uuid == BTA_A2DP_SOURCE_SERVICE_ID)
+            {
+                if (bt_av_src_callbacks)
+                {
+                    bt_av_src_callbacks = NULL;
+                    if (bt_av_sink_callbacks != NULL)
+                        break;
+                }
+            }
+            else
+            {
+                if (bt_av_sink_callbacks)
+                {
+                    bt_av_sink_callbacks = NULL;
+                    if (bt_av_src_callbacks != NULL)
+                        break;
+                }
+            }
+
+            btif_a2dp_stop_media_task();
+            return;
+        case BTIF_AV_CONNECT_REQ_EVT:
+            break;
+        case BTIF_AV_DISCONNECT_REQ_EVT:
+            /*Bd address passed should help us in getting the handle*/
+            bt_addr = (bt_bdaddr_t *)p_param;
+            index = btif_av_idx_by_bdaddr(bt_addr->address);
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+            if (bt_split_a2dp_enabled && (btif_av_get_current_playing_dev_idx() == index))
+            {
+                BTIF_TRACE_DEBUG("%s:Disconnecting playing device,send VS STOP",__func__);
+                btif_media_on_stop_vendor_command();
+            }
+#endif
+            break;
+        case BTIF_AV_UPDATE_ENCODER_REQ_EVT:
+        case BTIF_AV_START_STREAM_REQ_EVT:
+            /* Get the last connected device on which START can be issued
+            * Get the Dual A2dp Handoff Device first, if none is present,
+            * go for lastest connected.
+            * In A2dp Multicast, the index selected can be any of the
+            * connected device. Stack will ensure to START the steaming
+            * on both the devices. */
+            index = btif_get_latest_device_idx_to_start();
+            break;
+        case BTIF_AV_STOP_STREAM_REQ_EVT:
+        case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
+            /*Should be handled by current STARTED*/
+            index = btif_get_latest_playing_device_idx();
+            if ((index < btif_max_av_clients) && (index == btif_get_is_remote_started_idx()))
+            {
+                BTIF_TRACE_IMP("%s: Postpone handling suspend/stop req @ index = %d",
+                    __FUNCTION__, index);
+                return;
+            }
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+            if (bt_split_a2dp_enabled)
+                btif_media_on_stop_vendor_command();
+#endif
+            break;
+        case BTIF_AV_REMOTE_SUSPEND_STREAM_REQ_EVT:
+            index = btif_get_is_remote_started_idx();
+            if (index >= btif_max_av_clients)
+            {
+                BTIF_TRACE_ERROR("%s: Invalid index for connection", __FUNCTION__);
+                return;
+            }
+            BTIF_TRACE_IMP("%s: Remote Started set @ index = %d", __FUNCTION__, index);
+            btif_av_cb[index].is_remote_start_received = FALSE;
+            btif_av_cb[index].is_suspend_for_remote_start = TRUE;
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+            if ((bt_split_a2dp_enabled) && (!btif_av_is_playing_on_other_idx(index)))
+            {
+                BTIF_TRACE_IMP("%s: Other index is not playing", __FUNCTION__);
+                btif_media_on_stop_vendor_command();
+            }
+#endif
+            event = BTIF_AV_SUSPEND_STREAM_REQ_EVT;
+            break;
+        case BTIF_AV_RESET_REMOTE_STARTED_FLAG_UPDATE_AUDIO_STATE_EVT:
+            index = btif_get_is_remote_started_idx();
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
+            {
+                BTIF_TRACE_IMP("%s: on remote start clean up update audio started state for index %d",
+                    __FUNCTION__, index);
+                btif_report_audio_state(BTAV_AUDIO_STATE_STARTED, &(btif_av_cb[index].peer_bda));
+            }
+        case BTIF_AV_RESET_REMOTE_STARTED_FLAG_EVT:
+            btif_av_reset_remote_started_flag();
+            return;
+        /*Events from the stack, BTA*/
+        case BTA_AV_ENABLE_EVT:
+            index = 0;
+            break;
+        case BTA_AV_REGISTER_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->registr.hndl);
+            break;
+        case BTA_AV_OPEN_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->open.hndl);
+            break;
+        case BTA_AV_ROLE_CHANGED_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->role_changed.hndl);
+            role = p_bta_data->role_changed.new_role;
+            BTIF_TRACE_EVENT("Role change: 0x%x: new role: %s",
+                p_bta_data->role_changed.hndl, (role == HOST_ROLE_SLAVE) ? "Slave" : "Master");
+            if (index >= 0 && index < btif_max_av_clients)
+            {
+                btif_av_cb[index].is_slave = (role == HOST_ROLE_SLAVE) ? TRUE : FALSE;
+                btif_av_update_multicast_state(index);
+            }
+            else
+            {
+                BTIF_TRACE_ERROR("%s: Invalid index for connection", __FUNCTION__);
+            }
+            return;
+        case BTA_AV_PENDING_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->pend.hndl);
+            break;
+        case BTA_AV_REJECT_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->reject.hndl);
+            break;
+        case BTA_AV_STOP_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->suspend.hndl);
+            break;
+        case BTA_AV_CLOSE_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->close.hndl);
+            break;
+        case BTA_AV_START_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->start.hndl);
+            break;
+        case BTA_AV_RECONFIG_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->reconfig.hndl);
+            break;
+        case BTA_AV_SUSPEND_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->suspend.hndl);
+            break;
+
+        /* Handle all RC events on default index. RC handling should take
+         * care of the events. All events come with BD Address
+         * Handled well in AV Opening, opened and started state
+         * AV Idle handler needs to take care of this event properly.
+         */
+        case BTA_AV_RC_OPEN_EVT:
+            index = btif_av_get_valid_idx_for_rc_events(p_bta_data->rc_open.peer_addr,
+                    p_bta_data->rc_open.rc_handle);
+            break;
+        case BTA_AV_RC_CLOSE_EVT:
+        /* If there is no entry in the connection table
+         * RC handler has to be called for cleanup.
+         * Directly call the RC handler as we cannot
+         * associate any AV handle to it.
+         */
+            index = btif_av_idx_by_bdaddr(p_bta_data->rc_open.peer_addr);
+            if (index == btif_max_av_clients)
+            {
+                btif_rc_handler(event, p_bta_data);
+            }
+            break;
+        case BTA_AV_RC_COLL_DETECTED_EVT:
+            index = btif_av_idx_by_bdaddr(p_bta_data->rc_col_detected.peer_addr);
+            break;
+        /* Let the RC handler decide on these passthrough cmds
+         * Use rc_handle to get the active AV device and use that mapping.
+         */
+        case BTA_AV_REMOTE_CMD_EVT:
+        case BTA_AV_VENDOR_CMD_EVT:
+        case BTA_AV_META_MSG_EVT:
+        case BTA_AV_RC_FEAT_EVT:
+        case BTA_AV_BROWSE_MSG_EVT:
+            index = 0;
+            BTIF_TRACE_EVENT("RC events: on index = %d", index);
+            break;
+        default:
+            BTIF_TRACE_ERROR("Unhandled event = %d", event);
+            break;
+    }
+    BTIF_TRACE_DEBUG("Handle the AV event = %x on index = %d", event, index);
+    if (index >= 0 && index < btif_max_av_clients)
+        btif_sm_dispatch(btif_av_cb[index].sm_handle, event, (void*)p_param);
+    else
+        BTIF_TRACE_ERROR("Unhandled Index = %d", index);
+    btif_av_event_free_data(event, p_param);
+
+}
+
+void btif_av_reset_remote_started_flag()
+{
+    int i;
+    BTIF_TRACE_DEBUG("btif_av_reset_remote_started_flag");
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (btif_av_cb[i].is_remote_start_received)
+            btif_av_cb[i].is_remote_start_received = FALSE;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_get_valid_idx
+**
+** Description      Check the validity of the current index for the connection
+**
+** Returns          Boolean
+**
+*******************************************************************************/
+
+static BOOLEAN btif_av_get_valid_idx(int idx)
+{
+    btif_sm_state_t state = btif_sm_get_state(btif_av_cb[idx].sm_handle);
+    return ((state == BTIF_AV_STATE_OPENED) ||
+            (state ==  BTIF_AV_STATE_STARTED) ||
+            (state == BTIF_AV_STATE_OPENING));
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_idx_by_bdaddr
+**
+** Description      Get the index corresponding to BD addr
+**
+** Returns          UNIT8
+**
+*******************************************************************************/
+
+UINT8 btif_av_idx_by_bdaddr(BD_ADDR bd_addr)
+{
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if ((bdcmp(bd_addr,
+                  btif_av_cb[i].peer_bda.address) == 0))
+            return i;
+    }
+    return i;
+}
+
+BOOLEAN btif_av_is_current_device(BD_ADDR address)
+{
+    UINT8 index;
+
+    index = btif_av_idx_by_bdaddr(address);
+    if ((index < btif_max_av_clients) && (btif_av_cb[index].current_playing)
+        && (!btif_av_cb[index].is_remote_start_received))
+    {
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         btif_get_latest_device_idx_to_start
+**
+** Description      Get the index of the AV where streaming is to be started
+**
+** Returns          int
+**
+*******************************************************************************/
+
+static int btif_get_latest_device_idx_to_start()
+{
+    int i, j;
+    BD_ADDR playing_address;
+
+    /* Get the device which sent PLAY command
+     * If found, START on that index.
+     */
+    memset(playing_address, 0, sizeof(BD_ADDR));
+    btif_rc_get_playing_device(playing_address);
+    if (bdcmp(playing_address, bd_addr_null) != 0)
+    {
+        /* Got some valid Playing device.
+         * Get the AV index for this device.
+         */
+        i = btif_av_idx_by_bdaddr(playing_address);
+        if (i == btif_max_av_clients)
+            return btif_max_av_clients;
+        BTIF_TRACE_EVENT("Got some valid Playing device; %d", i);
+        /*Clear the Current playing device*/
+        for (j = 0; j < btif_max_av_clients; j++)
+        {
+            if (j != i)
+              btif_av_cb[j].current_playing = FALSE;
+        }
+        /*Clear the Play command in RC*/
+        btif_rc_clear_playing_state(FALSE);
+        return i;
+    }
+
+    /*No playing device, get the latest*/
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (btif_av_cb[i].current_playing)
+            break;
+    }
+    if (i == btif_max_av_clients)
+    {
+        BTIF_TRACE_ERROR("Play on default");
+        i = 0; /*play on default*/
+    }
+    return i;
+}
+
+/*******************************************************************************
+**
+** Function         btif_get_latest_playing_device_idx
+**
+** Description      Get the index of AV where streaming is happening
+**
+** Returns          int
+**
+*******************************************************************************/
+
+int btif_get_latest_playing_device_idx()
+{
+    int i;
+    btif_sm_state_t state;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        if (state == BTIF_AV_STATE_STARTED)
+        {
+            BTIF_TRACE_IMP("Latest playing device index %d", i);
+            break;
+        }
+    }
+    return i;
+}
+
+/*******************************************************************************
+**
+** Function         btif_get_is_remote_started_idx
+**
+** Description      Get the index of AV where remote Start is received
+**
+** Returns          int
+**
+*******************************************************************************/
+
+int btif_get_is_remote_started_idx()
+{
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (btif_av_cb[i].is_remote_start_received == TRUE)
+        {
+            BTIF_TRACE_IMP("remote started set for device index %d", i);
+            break;
+        }
+    }
+    return i;
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_is_playing
+**
+** Description      Is AV in streaming state
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+
+BOOLEAN btif_av_is_playing()
+{
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        btif_av_cb[i].state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        if (btif_av_cb[i].state == BTIF_AV_STATE_STARTED)
+        {
+            BTIF_TRACE_EVENT("btif_av_is_playing on index= %d", i);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         btif_get_conn_state_of_device
+**
+** Description      Returns the state of AV scb
+**
+** Returns          int
+**
+*******************************************************************************/
+
+static int btif_get_conn_state_of_device(BD_ADDR address)
+{
+    btif_sm_state_t state = BTIF_AV_STATE_IDLE;
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if ((bdcmp(address,
+            btif_av_cb[i].peer_bda.address) == 0))
+        {
+            state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+            BTIF_TRACE_EVENT("BD Found: %02X %02X %02X %02X %02X %02X :state: %s",
+                address[5], address[4], address[3],
+                address[2], address[1], address[0],
+                dump_av_sm_state_name(state));
+        }
+    }
+    return state;
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_get_valid_idx_for_rc_events
+**
+** Description      gets th valid index for the RC event address
+**
+** Returns          int
+**
+*******************************************************************************/
+
+static int btif_av_get_valid_idx_for_rc_events(BD_ADDR bd_addr, int rc_handle)
+{
+    int index = 0;
+    /* First try to find if it is first event in AV IF
+    * both the handles would be in IDLE state, pick the first
+    * If we get second RC event while processing the priority
+    * for the first, reject the second connection. */
+
+    /*Get the index from connected SCBs*/
+    index = btif_av_idx_by_bdaddr(bd_addr);
+    if (index == btif_max_av_clients)
+    {
+        /* None of the SCBS matched
+        * Allocate free SCB, null address SCB*/
+        index = btif_av_idx_by_bdaddr(bd_null);
+        BTIF_TRACE_EVENT("btif_av_get_valid_idx_for_rc_events is %d", index);
+        if (index >= btif_max_av_clients)
+        {
+            BTIF_TRACE_EVENT("disconnect only AVRCP device rc_handle %d", rc_handle);
+            BTA_AvCloseRc(rc_handle);
+        }
+    }
+    return index;
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_check_rc_connection_priority
+**
+** Description      Handles Priority callback for RC connections
+**
+** Returns          void
+**
+*******************************************************************************/
+
+static void btif_av_check_rc_connection_priority(void *p_data)
+{
+    bt_bdaddr_t peer_bda;
+
+    /*Check if it is for same AV device*/
+    if (btif_av_is_device_connected(((tBTA_AV*)p_data)->rc_open.peer_addr))
+    {
+        /*AV is connected */
+        BTIF_TRACE_DEBUG("AV is connected, process RC connect event");
+        btif_rc_handler(BTA_AV_RC_OPEN_EVT, (tBTA_AV*)p_data);
+        return;
+    }
+    BTIF_TRACE_DEBUG("btif_av_check_rc_connection_priority");
+    bdcpy(peer_bda.address, ((tBTA_AV*)p_data)->rc_open.peer_addr);
+
+    if (idle_rc_event != 0)
+    {
+        BTIF_TRACE_DEBUG("Processing another RC Event ");
+        return;
+    }
+    idle_rc_event = BTA_AV_RC_OPEN_EVT;
+    memcpy(&idle_rc_data, ((tBTA_AV*)p_data), sizeof(tBTA_AV));
+    if (((tBTA_AV*)p_data)->rc_open.status == BTA_AV_SUCCESS)
+    {
+        BTIF_TRACE_DEBUG("RC conn is success ");
+        if (bt_av_src_callbacks != NULL)
+        {
+            BTIF_TRACE_DEBUG(" Check Device priority");
+            HAL_CBACK(bt_av_src_callbacks, connection_priority_cb,
+                    &peer_bda);
+        }
+    }
+    else
+    {
+        idle_rc_event = 0;
+        memset(&idle_rc_data, 0, sizeof(tBTA_AV));
+    }
+    return;
+}
+
+
 static void bte_av_callback(tBTA_AV_EVT event, tBTA_AV *p_data)
 {
     btif_transfer_context(btif_av_handle_event, event,
                           (char*)p_data, sizeof(tBTA_AV), btif_av_event_deep_copy);
 }
 
+/*Called only in case of A2dp SInk, which runs on index 0*/
 static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
 {
     btif_sm_state_t state;
@@ -1140,10 +2529,11 @@
     tA2D_STATUS a2d_status;
     tA2D_SBC_CIE sbc_cie;
     btif_av_sink_config_req_t config_req;
+    int index =0;
 
     if (event == BTA_AV_MEDIA_DATA_EVT)/* Switch to BTIF_MEDIA context */
     {
-        state= btif_sm_get_state(btif_av_cb.sm_handle);
+        state= btif_sm_get_state(btif_av_cb[index].sm_handle);
         if ( (state == BTIF_AV_STATE_STARTED) || /* send SBC packets only in Started State */
              (state == BTIF_AV_STATE_OPENED) )
         {
@@ -1171,6 +2561,79 @@
         }
     }
 }
+
+/******************************************************************************
+** Function       a2dp_offload_codec_cap_parser
+**
+** Description    Parse the offload supported codec capability during init
+**
+** Returns
+*****************************************************************************/
+static void a2dp_offload_codec_cap_parser(const char *value)
+{
+    char *tok = NULL;
+    char *tmp_token = NULL;
+    int size = 0;
+    char *tmp_copy_buf = NULL;
+    if (value == NULL)
+    {
+        BTIF_TRACE_ERROR("%s: Offload String is NULL",__func__);
+        return;
+    }
+    size = strlen(value) + 1;
+    tmp_copy_buf = (char *) osi_malloc (size);
+    if (tmp_copy_buf == NULL)
+    {
+        BTIF_TRACE_ERROR("%s: Memorey allocation failed",__func__);
+        return;
+    }
+    memset(tmp_copy_buf, 0, size);
+    memcpy(tmp_copy_buf, value, size - 1);
+    /* Fix for below Klockwork Issue
+     * 'strtok' has been deprecated; replace it with a safe function. */
+    tok = strtok_r((char*)tmp_copy_buf, "-", &tmp_token);
+    while (tok != NULL)
+    {
+        if (strcmp(tok,"sbc") == 0)
+        {
+            BTIF_TRACE_ERROR("%s: SBC offload supported",__func__);
+            btif_av_codec_offload.sbc_offload = TRUE;
+        }
+        else if (strcmp(tok,"aptx") == 0)
+        {
+            BTIF_TRACE_ERROR("%s: aptX offload supported",__func__);
+            btif_av_codec_offload.aptx_offload = TRUE;
+        }
+        else if (strcmp(tok,"aac") == 0)
+        {
+            BTIF_TRACE_ERROR("%s: AAC offload supported",__func__);
+            btif_av_codec_offload.aac_offload = TRUE;
+        }
+        else if (strcmp(tok,"aptxhd") == 0)
+        {
+            BTIF_TRACE_ERROR("%s: APTXHD offload supported",__func__);
+            btif_av_codec_offload.aptxhd_offload = TRUE;
+        }
+        tok = strtok_r(NULL, "-", &tmp_token);
+    };
+    osi_free_and_reset((void **) &tmp_copy_buf);
+}
+
+/******************************************************************************
+** Function       get_offload_codec_capabilities
+**
+** Description    Read offload supported codecs
+**                To set offload capabilities:
+**                adb shell setprop persist.bt.a2dp_offload_cap "sbc-aptx"
+**
+** Returns
+*****************************************************************************/
+static void get_offload_codec_capabilities(const char* codec_cap)
+{
+    BTIF_TRACE_DEBUG("%s",__func__);
+    a2dp_offload_codec_cap_parser(codec_cap);
+    return;
+}
 /*******************************************************************************
 **
 ** Function         btif_av_init
@@ -1183,20 +2646,29 @@
 
 bt_status_t btif_av_init(int service_id)
 {
-    if (btif_av_cb.sm_handle == NULL)
+    int i;
+    if (btif_av_cb[0].sm_handle == NULL)
     {
         alarm_free(av_open_on_rc_timer);
         av_open_on_rc_timer = alarm_new("btif_av.av_open_on_rc_timer");
-        if (!btif_a2dp_start_media_task())
+        alarm_free(av_coll_detected_timer);
+        av_coll_detected_timer = alarm_new("btif_av.av_coll_detected_timer");
+        BTIF_TRACE_DEBUG("%s", __FUNCTION__);
+        if(!btif_a2dp_is_media_task_stopped())
             return BT_STATUS_FAIL;
-
-        btif_enable_service(service_id);
+        btif_av_cb[0].service = service_id;
 
         /* Also initialize the AV state machine */
-        btif_av_cb.sm_handle =
-                btif_sm_init((const btif_sm_handler_t*)btif_av_state_handlers, BTIF_AV_STATE_IDLE);
+        for (i = 0; i < btif_max_av_clients; i++)
+        {
+            btif_av_cb[i].sm_handle = btif_sm_init((const btif_sm_handler_t*)btif_av_state_handlers,
+                                                    BTIF_AV_STATE_IDLE, i);
+        }
 
-        btif_a2dp_on_init();
+        btif_transfer_context(btif_av_handle_event, BTIF_AV_INIT_REQ_EVT,
+                (char*)&service_id, sizeof(int), NULL);
+
+        btif_enable_service(service_id);
     }
 
     return BT_STATUS_SUCCESS;
@@ -1212,13 +2684,36 @@
 **
 *******************************************************************************/
 
-static bt_status_t init_src(btav_callbacks_t* callbacks)
+static bt_status_t init_src(btav_callbacks_t* callbacks, int max_a2dp_connections,
+                            int a2dp_multicast_state, const char* offload_cap)
 {
-    BTIF_TRACE_EVENT("%s()", __func__);
+    bt_status_t status;
 
-    bt_status_t status = btif_av_init(BTA_A2DP_SOURCE_SERVICE_ID);
-    if (status == BT_STATUS_SUCCESS)
+    BTIF_TRACE_EVENT("%s with max conn = %d", __FUNCTION__, max_a2dp_connections);
+
+    if (bt_av_sink_callbacks != NULL) {
+        // already did btif_av_init()
+        status = BT_STATUS_SUCCESS;
+    }
+    else
+    {
+        if (a2dp_multicast_state)
+        {
+            is_multicast_supported = TRUE;
+        }
+        if (offload_cap)
+        {
+            bt_split_a2dp_enabled = TRUE;
+            get_offload_codec_capabilities(offload_cap);
+            is_multicast_supported = FALSE; //Disable multicast in Split A2dp mode
+        }
+        btif_max_av_clients = max_a2dp_connections;
+        status = btif_av_init(BTA_A2DP_SOURCE_SERVICE_ID);
+    }
+
+    if (status == BT_STATUS_SUCCESS) {
         bt_av_src_callbacks = callbacks;
+    }
 
     return status;
 }
@@ -1233,13 +2728,34 @@
 **
 *******************************************************************************/
 
-static bt_status_t init_sink(btav_callbacks_t* callbacks)
+static bt_status_t init_sink(btav_callbacks_t* callbacks, int max,
+                             int a2dp_multicast_state, const char *offload_cap)
 {
-    BTIF_TRACE_EVENT("%s()", __func__);
+    bt_status_t status;
 
-    bt_status_t status = btif_av_init(BTA_A2DP_SINK_SERVICE_ID);
-    if (status == BT_STATUS_SUCCESS)
+    BTIF_TRACE_EVENT("%s", __FUNCTION__);
+
+    if (bt_av_src_callbacks != NULL) {
+        // already did btif_av_init()
+        status = BT_STATUS_SUCCESS;
+    }
+    else
+    {
+        enable_multicast = FALSE; // Clear multicast flag for sink
+        bt_split_a2dp_enabled = FALSE; //Clear split a2dp for sink
+        if (max > 1)
+        {
+            BTIF_TRACE_ERROR("Only one Sink can be initialized");
+            max = 1;
+        }
+        btif_max_av_clients = max; //Should be 1
+        status = btif_av_init(BTA_A2DP_SINK_SERVICE_ID);
+    }
+
+    if (status == BT_STATUS_SUCCESS) {
         bt_av_sink_callbacks = callbacks;
+        //BTA_AvEnable_Sink(TRUE);
+    }
 
     return status;
 }
@@ -1277,6 +2793,119 @@
 }
 #endif
 
+
+void btif_get_latest_playing_device(BD_ADDR address)
+{
+    int index;
+    index = btif_get_latest_playing_device_idx();
+    if (index < btif_max_av_clients)
+    {
+        //copy bdaddrsss
+        bdcpy(address, btif_av_cb[index].peer_bda.address);
+    }
+    else
+    {
+        bdcpy(address, bd_null);
+    }
+}
+
+BOOLEAN btif_av_is_device_connected(BD_ADDR address)
+{
+    btif_sm_state_t state = btif_get_conn_state_of_device(address);
+
+    if ((state == BTIF_AV_STATE_OPENED) ||
+        (state == BTIF_AV_STATE_STARTED))
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/*This function will trigger remote suspend for currently
+* playing device and then initiate START on Handoff device
+* whose address is passed as an argument. */
+/*******************************************************************************
+**
+** Function         btif_av_trigger_dual_handoff
+**
+** Description      Trigger the DUAL HANDOFF
+**
+** Returns          void
+**
+*******************************************************************************/
+
+void btif_av_trigger_dual_handoff(BOOLEAN handoff, BD_ADDR address)
+{
+    int index,next_idx;
+    /*Get the current playing device*/
+    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
+    index = btif_get_latest_playing_device_idx();
+    if (index != btif_max_av_clients)
+    {
+        btif_av_cb[index].dual_handoff = handoff; /*Initiate Handoff*/
+        if (bt_split_a2dp_enabled)
+            btif_media_on_stop_vendor_command();
+        /*Initiate SUSPEND for this device*/
+
+        next_idx = btif_av_get_other_connected_idx(index);
+        if (next_idx != INVALID_INDEX && next_idx != btif_max_av_clients)
+        {
+            if (btif_av_cb[next_idx].is_remote_start_received)
+            {
+                btif_media_on_cancel_remote_start_alarm();
+                BTIF_TRACE_DEBUG("Reset remote start alarm on index = %d", next_idx);
+                btif_av_cb[next_idx].is_remote_start_received = FALSE;
+            }
+        }
+        BTIF_TRACE_DEBUG("Initiate SUSPEND for this device on index = %d", index);
+        btif_sm_dispatch(btif_av_cb[index].sm_handle, BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL);
+    }
+    else
+    {
+        BTIF_TRACE_ERROR("Handoff on invalid index");
+    }
+    if (bt_split_a2dp_enabled)
+    {
+        next_idx = btif_av_get_other_connected_idx(index);
+        /* Fix for below Klockwork Issue
+        Array 'btif_av_cb' of size 2 may use index value(s) -1 */
+        if (next_idx != INVALID_INDEX && next_idx != btif_max_av_clients)
+        {
+            reconfig_a2dp = TRUE;
+            HAL_CBACK(bt_av_src_callbacks, reconfig_a2dp_trigger_cb, 1,
+                                    &(btif_av_cb[next_idx].peer_bda));
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_trigger_suspend
+**
+** Description      Trigger suspend when multicast is ongoing for tuch tones
+**                  and new ACL is created.
+**
+** Returns          void
+**
+*******************************************************************************/
+
+void btif_av_trigger_suspend()
+{
+    int index;
+    /*Get the current playing device*/
+    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
+    index = btif_get_latest_playing_device_idx();
+    if (index <= btif_max_av_clients)
+    {
+        /*Initiate SUSPEND for this device*/
+        BTIF_TRACE_DEBUG("Initiate SUSPEND for this device on index = %d", index);
+        btif_sm_dispatch(btif_av_cb[index].sm_handle, BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL);
+    }
+    else
+    {
+        BTIF_TRACE_ERROR("suspend on invalid index");
+    }
+}
+
 /*******************************************************************************
 **
 ** Function         connect
@@ -1290,11 +2919,49 @@
 static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid)
 {
     btif_av_connect_req_t connect_req;
+    int i;
     connect_req.target_bda = bd_addr;
     connect_req.uuid = uuid;
     BTIF_TRACE_EVENT("%s", __FUNCTION__);
 
-    btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char*)&connect_req);
+    for (i = 0; i < btif_max_av_clients;)
+    {
+        if(btif_av_get_valid_idx(i))
+        {
+            if (bdcmp(bd_addr->address, btif_av_cb[i].peer_bda.address) == 0)
+            {
+                BTIF_TRACE_ERROR("Attempting connection for non idle device.. back off ");
+                btif_queue_advance();
+                return BT_STATUS_SUCCESS;
+            }
+            i++;
+        }
+        else
+            break;
+    }
+    if (i == btif_max_av_clients)
+    {
+        UINT8 rc_handle;
+
+        BTIF_TRACE_ERROR("%s: All indexes are full", __FUNCTION__);
+
+        btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, bd_addr);
+
+        /* Multicast: Check if AV slot is available for connection
+         * If not available, AV got connected to different devices.
+         * Disconnect this RC connection without AV connection.
+         */
+        rc_handle = btif_rc_get_connected_peer_handle(bd_addr->address);
+        if (rc_handle != BTIF_RC_HANDLE_NONE)
+        {
+            BTA_AvCloseRc(rc_handle);
+        }
+        btif_queue_advance();
+        return BT_STATUS_FAIL;
+    }
+
+    btif_sm_dispatch(btif_av_cb[i].sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char*)&connect_req);
+
 
     return BT_STATUS_SUCCESS;
 }
@@ -1346,37 +3013,73 @@
 *******************************************************************************/
 static void cleanup(int service_uuid)
 {
-    BTIF_TRACE_EVENT("%s", __FUNCTION__);
+    BTIF_TRACE_IMP("AV %s", __FUNCTION__);
 
-    btif_transfer_context(btif_av_handle_event, BTIF_AV_CLEANUP_REQ_EVT, NULL, 0, NULL);
+    btif_transfer_context(btif_av_handle_event, BTIF_AV_CLEANUP_REQ_EVT,
+            (char*)&service_uuid, sizeof(int), NULL);
 
     btif_disable_service(service_uuid);
-
-    /* Also shut down the AV state machine */
-    btif_sm_shutdown(btif_av_cb.sm_handle);
-    btif_av_cb.sm_handle = NULL;
 }
 
 static void cleanup_src(void) {
     BTIF_TRACE_EVENT("%s", __FUNCTION__);
-
-    if (bt_av_src_callbacks)
-    {
-        bt_av_src_callbacks = NULL;
-        if (bt_av_sink_callbacks == NULL)
-            cleanup(BTA_A2DP_SOURCE_SERVICE_ID);
-    }
+    cleanup(BTA_A2DP_SOURCE_SERVICE_ID);
+    BTIF_TRACE_EVENT("%s completed", __FUNCTION__);
 }
 
 static void cleanup_sink(void) {
     BTIF_TRACE_EVENT("%s", __FUNCTION__);
+    cleanup(BTA_A2DP_SINK_SERVICE_ID);
+}
 
-    if (bt_av_sink_callbacks)
+static void allow_connection(int is_valid, bt_bdaddr_t *bd_addr)
+{
+    int index = 0;
+    BTIF_TRACE_DEBUG(" %s isValid is %d event %d", __FUNCTION__,is_valid,idle_rc_event);
+    switch (idle_rc_event)
     {
-        bt_av_sink_callbacks = NULL;
-        if (bt_av_src_callbacks == NULL)
-            cleanup(BTA_A2DP_SINK_SERVICE_ID);
+        case BTA_AV_RC_OPEN_EVT:
+            if (is_valid)
+            {
+                BTIF_TRACE_DEBUG("allowconn for RC connection");
+				alarm_set_on_queue(av_open_on_rc_timer,
+						  BTIF_TIMEOUT_AV_OPEN_ON_RC_MS,
+						  btif_initiate_av_open_timer_timeout, NULL,
+						  btu_general_alarm_queue);
+                btif_rc_handler(idle_rc_event, &idle_rc_data);
+            }
+            else
+            {
+                UINT8 rc_handle =  idle_rc_data.rc_open.rc_handle;
+                BTA_AvCloseRc(rc_handle);
+            }
+            break;
+
+        case BTA_AV_PENDING_EVT:
+            if (is_valid)
+            {
+                index = btif_av_idx_by_bdaddr(bd_addr->address);
+                if (index >= btif_max_av_clients)
+                {
+                    BTIF_TRACE_DEBUG("Invalid index for device");
+                    break;
+                }
+                BTIF_TRACE_DEBUG("The connection is allowed for the device at index = %d", index);
+                BTA_AvOpen(btif_av_cb[index].peer_bda.address, btif_av_cb[index].bta_handle,
+                       TRUE, BTA_SEC_AUTHENTICATE, UUID_SERVCLASS_AUDIO_SOURCE);
+            }
+            else
+            {
+                BTA_AvDisconnect(idle_rc_data.pend.bd_addr);
+            }
+            break;
+
+        default:
+            BTIF_TRACE_DEBUG("%s : unhandled event:%s", __FUNCTION__,
+                                dump_av_sm_event_name(idle_rc_event));
     }
+    idle_rc_event = 0;
+    memset(&idle_rc_data, 0, sizeof(tBTA_AV));
 }
 
 static const btav_interface_t bt_av_src_interface = {
@@ -1387,6 +3090,7 @@
     cleanup_src,
     NULL,
     NULL,
+    allow_connection,
 };
 
 static const btav_interface_t bt_av_sink_interface = {
@@ -1402,6 +3106,7 @@
     NULL,
     NULL,
 #endif
+	NULL,
 };
 
 /*******************************************************************************
@@ -1413,10 +3118,11 @@
 ** Returns          None
 **
 *******************************************************************************/
-
+/* Media task uses this info
+* But dont use it. */
 btif_sm_handle_t btif_av_get_sm_handle(void)
 {
-    return btif_av_cb.sm_handle;
+    return btif_av_cb[0].sm_handle;
 }
 
 /*******************************************************************************
@@ -1429,9 +3135,17 @@
 **
 *******************************************************************************/
 
-bt_bdaddr_t btif_av_get_addr(void)
+bt_bdaddr_t btif_av_get_addr(BD_ADDR address)
 {
-    return btif_av_cb.peer_bda;
+    int i;
+    bt_bdaddr_t not_found ;
+    memset (&not_found, 0, sizeof(bt_bdaddr_t));
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (bdcmp(btif_av_cb[i].peer_bda.address, address) == 0)
+            return btif_av_cb[i].peer_bda;
+    }
+    return not_found;
 }
 
 /*******************************************************************************
@@ -1460,11 +3174,8 @@
 
 BOOLEAN btif_av_stream_ready(void)
 {
-    btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
-
-    BTIF_TRACE_DEBUG("btif_av_stream_ready : sm hdl %d, state %d, flags %x",
-                btif_av_cb.sm_handle, state, btif_av_cb.flags);
-
+    int i;
+    BOOLEAN status = FALSE;
     /* also make sure main adapter is enabled */
     if (btif_is_enabled() == 0)
     {
@@ -1472,11 +3183,35 @@
         return FALSE;
     }
 
-    /* check if we are remotely suspended or stop is pending */
-    if (btif_av_cb.flags & (BTIF_AV_FLAG_REMOTE_SUSPEND|BTIF_AV_FLAG_PENDING_STOP))
-        return FALSE;
-
-    return (state == BTIF_AV_STATE_OPENED);
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        btif_av_cb[i].state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        /* Multicast:
+         * If any of the stream is in pending suspend state when
+         * we initiate start, it will result in inconsistent behavior
+         * Check the pending SUSPEND flag and return failure
+         * if suspend is in progress.
+         */
+        BTIF_TRACE_DEBUG("btif_av_stream_ready flags: %d", btif_av_cb[i].flags);
+        if (btif_av_cb[i].dual_handoff ||
+            (btif_av_cb[i].flags & BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING))
+        {
+            status = FALSE;
+            break;
+        }
+        else if (btif_av_cb[i].flags &
+            (BTIF_AV_FLAG_REMOTE_SUSPEND|BTIF_AV_FLAG_PENDING_STOP|BTIF_AV_FLAG_PENDING_DISCONNECT))
+        {
+            status = FALSE;
+            break;
+        }
+        else if (btif_av_cb[i].state == BTIF_AV_STATE_OPENED)
+        {
+            status = TRUE;
+        }
+    }
+    BTIF_TRACE_DEBUG("btif_av_stream_ready: %d", status);
+    return status;
 }
 
 /*******************************************************************************
@@ -1491,19 +3226,68 @@
 
 BOOLEAN btif_av_stream_started_ready(void)
 {
-    btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
+    int i;
+    BOOLEAN status = FALSE;
 
-    BTIF_TRACE_DEBUG("btif_av_stream_started : sm hdl %d, state %d, flags %x",
-                btif_av_cb.sm_handle, state, btif_av_cb.flags);
-
-    /* disallow media task to start if we have pending actions */
-    if (btif_av_cb.flags & (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING | BTIF_AV_FLAG_REMOTE_SUSPEND
-        | BTIF_AV_FLAG_PENDING_STOP))
-        return FALSE;
-
-    return (state == BTIF_AV_STATE_STARTED);
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        btif_av_cb[i].state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        if (btif_av_cb[i].dual_handoff)
+        {
+            BTIF_TRACE_ERROR("%s: Under Dual handoff ",__FUNCTION__ );
+            status = FALSE;
+            break;
+        } else if (btif_av_cb[i].flags &
+            (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING |
+            BTIF_AV_FLAG_REMOTE_SUSPEND |
+            BTIF_AV_FLAG_PENDING_STOP))
+        {
+            status = FALSE;
+            break;
+        } else if (btif_av_cb[i].state == BTIF_AV_STATE_STARTED)
+        {
+            status = TRUE;
+        }
+    }
+    BTIF_TRACE_DEBUG("btif_av_stream_started_ready: %d", status);
+    return status;
 }
 
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+/*******************************************************************************
+**
+** Function         btif_av_stream_started_ready
+**
+** Description      Checks whether AV ready for media start in streaming state
+**
+** Returns          None
+**
+*******************************************************************************/
+
+BOOLEAN btif_av_is_suspend_stop_pending_ack(void)
+{
+    int i;
+    BOOLEAN status = FALSE;
+
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        btif_av_cb[i].state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        BTIF_TRACE_DEBUG("btif_av_stream_ready flags: %d, state: %d",
+                                btif_av_cb[i].flags, btif_av_cb[i].state);
+        if ((btif_av_cb[i].flags &
+            (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING |
+            BTIF_AV_FLAG_PENDING_STOP)) &&
+            (btif_av_cb[i].state == BTIF_AV_STATE_STARTED))
+        {
+            status = TRUE;
+            break;
+        }
+    }
+    BTIF_TRACE_DEBUG("btif_av_is_stream_suspend_pending_ack: %d", status);
+    return status;
+}
+#endif
+
 /*******************************************************************************
 **
 ** Function         btif_dispatch_sm_event
@@ -1518,8 +3302,10 @@
 void btif_dispatch_sm_event(btif_av_sm_event_t event, void *p_data, int len)
 {
     /* Switch to BTIF context */
+    BTIF_TRACE_IMP("%s: event: %d, len: %d", __FUNCTION__, event, len);
     btif_transfer_context(btif_av_handle_event, event,
                           (char*)p_data, len, NULL);
+    BTIF_TRACE_IMP("%s: event %d sent", __FUNCTION__, event);
 }
 
 /*******************************************************************************
@@ -1533,37 +3319,66 @@
 *******************************************************************************/
 bt_status_t btif_av_execute_service(BOOLEAN b_enable)
 {
-     if (b_enable)
-     {
-         /* TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not
-          * handle this request in order to allow incoming connections to succeed.
-          * We need to put this back once support for this is added */
+    int i;
+    btif_sm_state_t state;
+    BTIF_TRACE_IMP("%s: enable: %d", __FUNCTION__, b_enable);
+    if (b_enable)
+    {
+        /* TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not
+        * handle this request in order to allow incoming connections to succeed.
+        * We need to put this back once support for this is added */
 
-         /* Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
-          * auto-suspend av streaming on AG events(SCO or Call). The suspend shall
-          * be initiated by the app/audioflinger layers */
-         /* Support for browsing for SDP record should work only if we enable BROWSE
-          * while registering. */
+        /* Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
+        * auto-suspend av streaming on AG events(SCO or Call). The suspend shall
+        * be initiated by the app/audioflinger layers */
 #if (AVRC_METADATA_INCLUDED == TRUE)
-         BTA_AvEnable(BTA_SEC_AUTHENTICATE,
-             BTA_AV_FEAT_RCTG|BTA_AV_FEAT_METADATA|BTA_AV_FEAT_VENDOR|BTA_AV_FEAT_NO_SCO_SSPD
+        BTA_AvEnable(BTA_SEC_AUTHENTICATE,
+            BTA_AV_FEAT_RCTG|BTA_AV_FEAT_METADATA|BTA_AV_FEAT_VENDOR|BTA_AV_FEAT_NO_SCO_SSPD
+            |BTA_AV_FEAT_ACP_START
 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
-             |BTA_AV_FEAT_RCCT
-             |BTA_AV_FEAT_ADV_CTRL
+            |BTA_AV_FEAT_RCCT
+            |BTA_AV_FEAT_ADV_CTRL
+			|BTA_AV_FEAT_BROWSE
 #endif
-             ,bte_av_callback);
+            ,bte_av_callback);
 #else
-         BTA_AvEnable(BTA_SEC_AUTHENTICATE, (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_NO_SCO_SSPD),
-                      bte_av_callback);
+        BTA_AvEnable(BTA_SEC_AUTHENTICATE, (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_NO_SCO_SSPD
+            |BTA_AV_FEAT_ACP_START), bte_av_callback);
 #endif
-         BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AV_SERVICE_NAME, 0, bte_av_media_callback,
-                                                             UUID_SERVCLASS_AUDIO_SOURCE);
-     }
-     else {
-         BTA_AvDeregister(btif_av_cb.bta_handle);
-         BTA_AvDisable();
-     }
-     return BT_STATUS_SUCCESS;
+        for (i = 0; i < btif_max_av_clients; i++)
+        {
+            BTIF_TRACE_DEBUG("%s: BTA_AvRegister : %d", __FUNCTION__, i);
+            BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AV_SERVICE_NAME, 0, bte_av_media_callback,
+            UUID_SERVCLASS_AUDIO_SOURCE);
+        }
+        BTA_AvUpdateMaxAVClient(btif_max_av_clients);
+    }
+    else
+    {
+        /* Also shut down the AV state machine */
+        for (i = 0; i < btif_max_av_clients; i++ )
+        {
+            if (btif_av_cb[i].sm_handle != NULL)
+            {
+                state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+                if(state==BTIF_AV_STATE_OPENING)
+                {
+                    BTIF_TRACE_DEBUG("Moving State from Opening to Idle due to BT ShutDown");
+                    btif_sm_change_state(btif_av_cb[i].sm_handle, BTIF_AV_STATE_IDLE);
+                    btif_queue_advance();
+                }
+                btif_sm_shutdown(btif_av_cb[i].sm_handle);
+                btif_av_cb[i].sm_handle = NULL;
+            }
+        }
+        for (i = 0; i < btif_max_av_clients; i++)
+        {
+            BTA_AvDeregister(btif_av_cb[i].bta_handle);
+        }
+        BTA_AvDisable();
+    }
+    BTIF_TRACE_IMP("%s: enable: %d completed", __FUNCTION__, b_enable);
+    return BT_STATUS_SUCCESS;
 }
 
 /*******************************************************************************
@@ -1577,6 +3392,9 @@
 *******************************************************************************/
 bt_status_t btif_av_sink_execute_service(BOOLEAN b_enable)
 {
+     int i;
+     BTIF_TRACE_IMP("%s: enable: %d", __FUNCTION__, b_enable);
+
      if (b_enable)
      {
          /* Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
@@ -1590,9 +3408,20 @@
                                                                 UUID_SERVCLASS_AUDIO_SINK);
      }
      else {
-         BTA_AvDeregister(btif_av_cb.bta_handle);
-         BTA_AvDisable();
+         /* Also shut down the AV state machine */
+        for (i = 0; i < btif_max_av_clients; i++ )
+        {
+            if (btif_av_cb[i].sm_handle != NULL)
+            {
+                BTIF_TRACE_IMP("%s: shutting down AV SM", __FUNCTION__);
+                btif_sm_shutdown(btif_av_cb[i].sm_handle);
+                btif_av_cb[i].sm_handle = NULL;
+            }
+        }
+        BTA_AvDeregister(btif_av_cb[0].bta_handle);
+        BTA_AvDisable();
      }
+     BTIF_TRACE_IMP("%s: enable: %d completed", __FUNCTION__, b_enable);
      return BT_STATUS_SUCCESS;
 }
 
@@ -1637,8 +3466,119 @@
 *******************************************************************************/
 BOOLEAN btif_av_is_connected(void)
 {
-    btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
-    return ((state == BTIF_AV_STATE_OPENED) || (state ==  BTIF_AV_STATE_STARTED));
+    int i;
+    BOOLEAN status = FALSE;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        btif_av_cb[i].state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        if ((btif_av_cb[i].state == BTIF_AV_STATE_OPENED) ||
+            (btif_av_cb[i].state ==  BTIF_AV_STATE_STARTED))
+            status = TRUE;
+    }
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_is_connected_on_other_idx
+**
+** Description      Checks if any other AV SCB is connected
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+
+BOOLEAN btif_av_is_connected_on_other_idx(int current_index)
+{
+    //return true if other IDx is connected
+    btif_sm_state_t state = BTIF_AV_STATE_IDLE;
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (i != current_index)
+        {
+            state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+            if ((state == BTIF_AV_STATE_OPENED) ||
+                (state == BTIF_AV_STATE_STARTED))
+                return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_get_other_connected_idx
+**
+** Description      Checks if any AV SCB is connected other than the current
+**                  index
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+int btif_av_get_other_connected_idx(int current_index)
+{
+    //return true if other IDx is connected
+    btif_sm_state_t state = BTIF_AV_STATE_IDLE;
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (i != current_index)
+        {
+            state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+            if ((state == BTIF_AV_STATE_OPENED) ||
+                (state == BTIF_AV_STATE_STARTED))
+                return i;
+        }
+    }
+    return INVALID_INDEX;
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_is_playing_on_other_idx
+**
+** Description      Checks if any other AV SCB is connected
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+
+BOOLEAN btif_av_is_playing_on_other_idx(int current_index)
+{
+    //return true if other IDx is playing
+    btif_sm_state_t state = BTIF_AV_STATE_IDLE;
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (i != current_index)
+        {
+            state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+            if (state == BTIF_AV_STATE_STARTED)
+                return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_update_current_playing_device
+**
+** Description      Update the next connected device as playing
+**
+** Returns          void
+**
+*******************************************************************************/
+
+static void btif_av_update_current_playing_device(int index)
+{
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (i != index)
+            btif_av_cb[i].current_playing = TRUE;
+    }
 }
 
 /*******************************************************************************
@@ -1655,12 +3595,91 @@
 *******************************************************************************/
 BOOLEAN btif_av_is_peer_edr(void)
 {
+    btif_sm_state_t state;
+    BOOLEAN peer_edr = FALSE;
+
     ASSERTC(btif_av_is_connected(), "No active a2dp connection", 0);
 
-    if (btif_av_cb.edr)
-        return TRUE;
-    else
-        return FALSE;
+    /* If any of the remote in streaming state is BR
+     * return FALSE to ensure proper configuration
+     * is used. Ideally, since multicast is not supported
+     * if any of the connected device is BR device,
+     * we should not see both devices in START state.
+     */
+    for (int index = 0; index < btif_max_av_clients; index ++)
+    {
+        state = btif_sm_get_state(btif_av_cb[index].sm_handle);
+        if ((btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START)
+            || (state == BTIF_AV_STATE_STARTED))
+        {
+            if (btif_av_cb[index].edr)
+            {
+                peer_edr = TRUE;
+            }
+            else
+            {
+                return FALSE;
+            }
+        }
+    }
+    return peer_edr;
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_any_br_peer
+**
+** Description      Check if the any of connected devices is BR device.
+**
+** Returns          TRUE if connected to any BR device, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN btif_av_any_br_peer(void)
+{
+    btif_sm_state_t state;
+    for (int index = 0; index < btif_max_av_clients; index ++)
+    {
+        state = btif_sm_get_state(btif_av_cb[index].sm_handle);
+        if (state >= BTIF_AV_STATE_OPENED)
+        {
+            if (!btif_av_cb[index].edr)
+            {
+                BTIF_TRACE_WARNING("%s : Connected to BR device :", __FUNCTION__);
+                return TRUE;
+            }
+        }
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_peer_supports_3mbps
+**
+** Description      check if the connected a2dp device supports
+**                  3mbps edr. Only when connected this function
+**                  will accurately provide a true capability of
+**                  remote peer. If not connected it will always be false.
+**
+** Returns          TRUE if remote device is EDR and supports 3mbps
+**
+*******************************************************************************/
+BOOLEAN btif_av_peer_supports_3mbps(void)
+{
+    btif_sm_state_t state;
+    ASSERTC(btif_av_is_connected(), "No active a2dp connection", 0);
+
+    for (int index = 0; index < btif_max_av_clients; index ++)
+    {
+        state = btif_sm_get_state(btif_av_cb[index].sm_handle);
+        if ((btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START)
+            || (state == BTIF_AV_STATE_STARTED))
+        {
+            if(btif_av_cb[index].edr_3mbps)
+                return TRUE;
+        }
+    }
+    return FALSE;
 }
 
 /******************************************************************************
@@ -1669,29 +3688,472 @@
 **
 ** Description     Clears btif_av_cd.flags if BTIF_AV_FLAG_REMOTE_SUSPEND is set
 **
-** Returns          void
+** Returns         void
 ******************************************************************************/
 void btif_av_clear_remote_suspend_flag(void)
 {
-    BTIF_TRACE_DEBUG("%s: flag :%x",__func__, btif_av_cb.flags);
-    btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        BTIF_TRACE_DEBUG(" flag :%x",btif_av_cb[i].flags);
+        btif_av_cb[i].flags  &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
+    }
 }
 
 /*******************************************************************************
 **
-** Function         btif_av_peer_supports_3mbps
+** Function         btif_av_move_idle
 **
-** Description      Check if the connected A2DP device supports
-**                  3 Mbps EDR. This function only works if connected.
-**                  If not connected it will always be false.
+** Description      Opening state is intermediate state. It cannot handle
+**                  incoming/outgoing connect/disconnect requests.When ACL
+**                  is disconnected and we are in opening state then move back
+**                  to idle state which is proper to handle connections.
 **
-** Returns          TRUE if remote device is EDR and supports 3 Mbps
+** Returns          Void
 **
 *******************************************************************************/
-BOOLEAN btif_av_peer_supports_3mbps(void)
+void btif_av_move_idle(bt_bdaddr_t bd_addr)
 {
-    BOOLEAN is3mbps = ((btif_av_cb.edr & BTA_AV_EDR_3MBPS) != 0);
-    BTIF_TRACE_DEBUG("%s: connected %d, edr_3mbps %d", __func__,
-            btif_av_is_connected(), is3mbps);
-    return (btif_av_is_connected() && is3mbps);
+    int index =0;
+    /* inform the application that ACL is disconnected and move to idle state */
+    index = btif_av_idx_by_bdaddr(bd_addr.address);
+    if (index == btif_max_av_clients)
+    {
+        BTIF_TRACE_DEBUG("btif_av_move_idle: Already in IDLE");
+        return;
+    }
+    btif_sm_state_t state = btif_sm_get_state(btif_av_cb[index].sm_handle);
+    BTIF_TRACE_DEBUG("ACL Disconnected state %d  is same device %d",state,
+            memcmp (&bd_addr, &(btif_av_cb[index].peer_bda), sizeof(bd_addr)));
+    if (state == BTIF_AV_STATE_OPENING &&
+            (memcmp (&bd_addr, &(btif_av_cb[index].peer_bda), sizeof(bd_addr)) == 0))
+    {
+        BTIF_TRACE_DEBUG("Moving BTIF State from Opening to Idle due to ACL disconnect");
+        btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb[index].peer_bda));
+        BTA_AvClose(btif_av_cb[index].bta_handle);
+        btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_IDLE);
+        btif_queue_advance();
+        btif_av_check_and_start_collission_timer(index);
+    }
 }
+/******************************************************************************
+**
+** Function        btif_av_get_num_playing_devices
+**
+** Description     Return number of A2dp playing devices
+**
+** Returns         int
+******************************************************************************/
+UINT16 btif_av_get_num_playing_devices(void)
+{
+    UINT16 i;
+    UINT16 playing_devices = 0;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        btif_av_cb[i].state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        if (btif_av_cb[i].state ==  BTIF_AV_STATE_STARTED)
+        {
+            playing_devices++;
+        }
+    }
+    BTIF_TRACE_DEBUG("AV devices playing: %d", playing_devices);
+
+    return playing_devices;
+}
+/*******************************************************************************
+**
+** Function        btif_av_get_num_connected_devices
+**
+** Description     Return number of A2dp connected devices
+**
+** Returns         int
+******************************************************************************/
+UINT16 btif_av_get_num_connected_devices(void)
+{
+    UINT16 i;
+    UINT16 connected_devies = 0;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        btif_av_cb[i].state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        if ((btif_av_cb[i].state == BTIF_AV_STATE_OPENED) ||
+            (btif_av_cb[i].state ==  BTIF_AV_STATE_STARTED))
+        {
+            connected_devies++;
+        }
+    }
+    BTIF_TRACE_DEBUG("AV Connection count: %d", connected_devies);
+
+    return connected_devies;
+}
+
+/******************************************************************************
+**
+** Function        btif_av_update_multicast_state
+**
+** Description     Enable Multicast only if below conditions are satisfied
+**                 1. Connected to only 2 EDR HS.
+**                 2. Connected to both HS as master.
+**                 3. Connected to 2 EDR HS and one BLE device
+**                 Multicast will fall back to soft handsoff in below conditions
+**                 1. Number of ACL links is more than 2,like connected to HID
+**                    initiating connection for HS1 and HS2.
+**                 2. Connected to BR and EDR HS.
+**                 3. Connected to more then 1 BLE device
+**
+** Returns         void
+******************************************************************************/
+void btif_av_update_multicast_state(int index)
+{
+    UINT16 num_connected_br_edr_devices = 0;
+    UINT16 num_connected_le_devices = 0;
+    UINT16 num_av_connected = 0;
+    UINT16 i = 0;
+    BOOLEAN is_slave = FALSE;
+    BOOLEAN is_br_hs_connected = FALSE;
+    BOOLEAN prev_multicast_state = enable_multicast;
+
+    if (!is_multicast_supported)
+    {
+        BTIF_TRACE_DEBUG("%s Multicast is Disabled", __FUNCTION__);
+        return;
+    }
+
+    if (multicast_disabled == TRUE)
+    {
+        multicast_disabled = FALSE;
+        enable_multicast = FALSE;
+        BTA_AvEnableMultiCast(FALSE, btif_av_cb[index].bta_handle);
+        return;
+    }
+
+    BTIF_TRACE_DEBUG("%s Multicast previous state : %s", __FUNCTION__,
+        enable_multicast ? "Enabled" : "Disabled" );
+
+    num_connected_br_edr_devices = btif_dm_get_br_edr_links();
+    num_connected_le_devices = btif_dm_get_le_links();
+    num_av_connected = btif_av_get_num_connected_devices();
+    is_br_hs_connected = btif_av_any_br_peer();
+
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (btif_av_cb[i].is_slave == TRUE)
+        {
+            BTIF_TRACE_WARNING("Conected as slave");
+            is_slave = TRUE;
+            break;
+        }
+    }
+
+    if ((num_av_connected <= 2) && (is_br_hs_connected != TRUE) &&
+        (is_slave == FALSE) && ((num_connected_br_edr_devices <= 2) &&
+        (num_connected_le_devices <= 1)))
+    {
+        enable_multicast = TRUE;
+    }
+    else
+    {
+        enable_multicast = FALSE;
+    }
+
+    BTIF_TRACE_DEBUG("%s Multicast current state : %s", __FUNCTION__,
+        enable_multicast ? "Enabled" : "Disabled" );
+
+    if (prev_multicast_state != enable_multicast)
+    {
+        BTA_AvEnableMultiCast(enable_multicast,
+                btif_av_cb[index].bta_handle);
+        HAL_CBACK(bt_av_src_callbacks, multicast_state_cb,
+              enable_multicast);
+    }
+}
+/******************************************************************************
+**
+** Function        btif_av_get_multicast_state
+**
+** Description     Returns TRUE if multicast is enabled else false
+**
+** Returns         BOOLEAN
+******************************************************************************/
+BOOLEAN btif_av_get_multicast_state()
+{
+    return enable_multicast;
+}
+/******************************************************************************
+**
+** Function        btif_av_get_ongoing_multicast
+**
+** Description     Returns TRUE if multicast is ongoing
+**
+** Returns         BOOLEAN
+******************************************************************************/
+BOOLEAN btif_av_get_ongoing_multicast()
+{
+    int i = 0, j = 0;
+    if (!is_multicast_supported)
+    {
+        BTIF_TRACE_DEBUG("Multicast is Disabled");
+        return FALSE;
+    }
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (btif_av_cb[i].is_device_playing)
+        {
+            j++;
+        }
+    }
+    if (j == btif_max_av_clients)
+    {
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+
+/******************************************************************************
+**
+** Function        btif_av_is_multicast_supported
+**
+** Description     Returns TRUE if multicast is supported
+**
+** Returns         BOOLEAN
+******************************************************************************/
+BOOLEAN btif_av_is_multicast_supported()
+{
+    return is_multicast_supported;
+}
+
+BOOLEAN btif_av_check_flag_remote_suspend(int index)
+{
+    BTIF_TRACE_ERROR("%s: index = %d",__FUNCTION__,index);
+    if (btif_av_cb[index].flags & BTIF_AV_FLAG_REMOTE_SUSPEND)
+    {
+        BTIF_TRACE_DEBUG("remote suspend flag set on index = %d",index);
+        return TRUE;
+    }
+    else
+    {
+        BTIF_TRACE_DEBUG("remote suspend flag not set on index = %d",index);
+        return FALSE;
+    }
+}
+
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+int btif_av_get_current_playing_dev_idx(void)
+{
+    int i;
+
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (btif_av_cb[i].current_playing == TRUE)
+        {
+            BTIF_TRACE_DEBUG("current playing on index = %d",i);
+            return i;
+        }
+    }
+    return -1;
+}
+/******************************************************************************
+**
+** Function         btif_av_get_streaming_channel_id
+**
+** Description     Returns streaming channel id
+**
+** Returns          channel id
+********************************************************************************/
+UINT16 btif_av_get_streaming_channel_id(void)
+{
+    int index;
+
+    index = btif_av_get_current_playing_dev_idx();
+    if (index != -1)
+    {
+        BTIF_TRACE_DEBUG("btif_av_get_streaming_channel_id: %u",
+                        btif_av_cb[index].channel_id);
+        return btif_av_cb[index].channel_id;
+    }
+    return 0;
+}
+
+/******************************************************************************
+**
+** Function         btif_av_get_peer_addr
+**
+** Description     Returns peer device address.
+**
+** Returns          peer address
+********************************************************************************/
+void btif_av_get_peer_addr(bt_bdaddr_t *peer_bda)
+{
+    btif_sm_state_t state = BTIF_AV_STATE_IDLE;
+    int i;
+    memset(peer_bda, 0, sizeof(bt_bdaddr_t));
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        if ((state == BTIF_AV_STATE_OPENED) ||
+            (state == BTIF_AV_STATE_STARTED))
+        {
+            BTIF_TRACE_DEBUG("btif_av_get_peer_addr: %u state: %d ",
+                    btif_av_cb[i].peer_bda, state);
+            memset(peer_bda, 0, sizeof(bt_bdaddr_t));
+            memcpy(peer_bda, &btif_av_cb[i].peer_bda,
+                                    sizeof(bt_bdaddr_t));
+            if (state == BTIF_AV_STATE_STARTED)
+                break;
+        }
+    }
+}
+
+/******************************************************************************
+**
+** Function         btif_av_get_playing_device_hdl
+**
+** Description      Returns current playing device's bta handle
+**
+** Returns         BTA HANDLE
+********************************************************************************/
+tBTA_AV_HNDL btif_av_get_playing_device_hdl()
+{
+    int i;
+    btif_sm_state_t state = BTIF_AV_STATE_IDLE;
+
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        if (state == BTIF_AV_STATE_STARTED)
+        {
+            return btif_av_cb[i].bta_handle;
+        }
+    }
+    return 0;
+}
+
+/******************************************************************************
+**
+** Function         btif_av_get_av_hdl_from_idx
+**
+** Description      Returns bta handle from the device index
+**
+** Returns         BTA HANDLE
+********************************************************************************/
+tBTA_AV_HNDL btif_av_get_av_hdl_from_idx(UINT8 idx)
+{
+    if (idx == btif_max_av_clients)
+    {
+        BTIF_TRACE_ERROR("%s: Invalid handle",__func__);
+        return -1;
+    }
+    return btif_av_cb[idx].bta_handle;
+}
+
+/******************************************************************************
+**
+** Function         btif_av_is_codec_offload_supported
+**
+** Description     check if the correpsonding codec is supported in offload
+**
+** Returns         TRUE if supported, FALSE otherwise
+********************************************************************************/
+BOOLEAN btif_av_is_codec_offload_supported(int codec)
+{
+    BOOLEAN ret = FALSE;
+    int retval;
+    char value[255] = "false";
+
+    BTIF_TRACE_DEBUG("btif_av_is_codec_offload_supported = %s",dump_av_codec_name(codec));
+    switch(codec)
+    {
+        case SBC:
+            ret = btif_av_codec_offload.sbc_offload;
+            break;
+        case APTX:
+            ret = btif_av_codec_offload.aptx_offload;
+            break;
+        case AAC:
+            ret = btif_av_codec_offload.aac_offload;
+            retval = property_get("persist.bt.a2dp.aac_disable", value, "false");
+            BTIF_TRACE_DEBUG("%s: property_get: bt.a2dp.aac_disable: %s, retval: %d", __func__, value, retval);
+            if (strncmp(value, "true", 5) == 0) {
+                ret = FALSE;
+            }
+            break;
+        case APTXHD:
+            ret = btif_av_codec_offload.aptxhd_offload;
+            break;
+        default:
+            ret = FALSE;
+    }
+    BTIF_TRACE_DEBUG("btif_av_is_codec_offload_supported %s codec supported = %d",dump_av_codec_name(codec),ret);
+    return ret;
+}
+
+/******************************************************************************
+**
+** Function         btif_av_is_under_handoff
+**
+** Description     check if AV state is under handoff
+**
+** Returns         TRUE if handoff is triggered, FALSE otherwise
+********************************************************************************/
+BOOLEAN btif_av_is_under_handoff()
+{
+    int i;
+    btif_sm_state_t state = BTIF_AV_STATE_IDLE;
+
+    BTIF_TRACE_DEBUG("btif_av_is_under_handoff");
+
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        if (btif_av_cb[i].dual_handoff &&
+            (state == BTIF_AV_STATE_STARTED || state == BTIF_AV_STATE_OPENED))
+        {
+            /* If a2dp reconfigure is triggered when playing device disconnect is
+             * initiated locally then return false, otherwise wait till the suspend cfm
+             * is received from the remote.
+             */
+            BTIF_TRACE_DEBUG("AV is under handoff");
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+BOOLEAN btif_av_is_device_disconnecting()
+{
+    int i;
+    btif_sm_state_t state = BTIF_AV_STATE_IDLE;
+    BTIF_TRACE_DEBUG("btif_av_is_device_disconnecting");
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        BTIF_TRACE_DEBUG("%s: state = %d",__func__,state);
+        if ((btif_av_cb[i].dual_handoff &&
+            state == BTIF_AV_STATE_CLOSING))
+        {
+            BTIF_TRACE_DEBUG("Device disconnecting");
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+void btif_av_reset_reconfig_flag()
+{
+    int i;
+    BTIF_TRACE_DEBUG("%s",__func__);
+    reconfig_a2dp = FALSE;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (btif_av_cb[i].dual_handoff)
+        {
+            BTIF_TRACE_DEBUG("%s resetting dual handoff flag for index %d",
+                __func__, i);
+            btif_av_cb[i].dual_handoff = FALSE;
+        }
+    }
+}
+#endif
+
diff --git a/btif/src/btif_avrcp_audio_track.cpp b/btif/src/btif_avrcp_audio_track.cpp
index cd9cf9a..89d2a5f 100644
--- a/btif/src/btif_avrcp_audio_track.cpp
+++ b/btif/src/btif_avrcp_audio_track.cpp
@@ -15,6 +15,8 @@
  */
 
 //#define LOG_NDEBUG 0
+#define LOG_TAG "bt_btif_avrcp_audio_track"
+
 #include "btif_avrcp_audio_track.h"
 
 #include <media/AudioTrack.h>
diff --git a/btif/src/btif_config.c b/btif/src/btif_config.c
index d5fb323..b2b4b68 100644
--- a/btif/src/btif_config.c
+++ b/btif/src/btif_config.c
@@ -188,8 +188,10 @@
   } else {
     time_t current_time = time(NULL);
     struct tm* time_created = localtime(&current_time);
-    strftime(btif_config_time_created, TIME_STRING_LENGTH, TIME_STRING_FORMAT, time_created);
-    config_set_string(config, INFO_SECTION, FILE_TIMESTAMP, btif_config_time_created);
+    if (time_created) {
+      strftime(btif_config_time_created, TIME_STRING_LENGTH, TIME_STRING_FORMAT, time_created);
+      config_set_string(config, INFO_SECTION, FILE_TIMESTAMP, btif_config_time_created);
+    }
   }
 
   // TODO(sharvil): use a non-wake alarm for this once we have
diff --git a/btif/src/btif_config_transcode.cpp b/btif/src/btif_config_transcode.cpp
index e9d859e..e8bd1a2 100644
--- a/btif/src/btif_config_transcode.cpp
+++ b/btif/src/btif_config_transcode.cpp
@@ -31,19 +31,19 @@
   XMLDocument document;
   int error = document.LoadFile(xml_filename);
   if (error != XML_SUCCESS) {
-    LOG_ERROR("%s unable to load XML file '%s': %d", __func__, xml_filename, error);
+    LOG_ERROR(LOG_TAG, "%s unable to load XML file '%s': %d", __func__, xml_filename, error);
     return NULL;
   }
 
   XMLElement *rootElement = document.RootElement();
   if (!rootElement) {
-    LOG_ERROR("%s unable to find root element; assuming corrupted config file.", __func__);
+    LOG_ERROR(LOG_TAG, "%s unable to find root element; assuming corrupted config file.", __func__);
     return NULL;
   }
 
   config_t *config = config_new_empty();
   if (!config) {
-    LOG_ERROR("%s unable to allocate config object.", __func__);
+    LOG_ERROR(LOG_TAG, "%s unable to allocate config object.", __func__);
     return NULL;
   }
 
diff --git a/btif/src/btif_core.c b/btif/src/btif_core.c
index c74c6dd..ef73e89 100644
--- a/btif/src/btif_core.c
+++ b/btif/src/btif_core.c
@@ -45,7 +45,6 @@
 #include "btif_api.h"
 #include "btif_av.h"
 #include "btif_config.h"
-#include "btif_config.h"
 #include "btif_pan.h"
 #include "btif_profile_queue.h"
 #include "btif_sock.h"
@@ -76,6 +75,12 @@
 #endif  // defined(OS_GENERIC)
 #endif  // BTE_DID_CONF_FILE
 
+#define VENDOR_PERSISTENCE_PATH    "/persist/bluetooth"
+#define VENDOR_BT_NV_FILE_NAME     ".bt_nv.bin"
+#define VENDOR_PAYLOAD_MAXLENGTH   (260)
+#define VENDOR_MAX_CMD_HDR_SIZE    (3)
+#define VENDOR_BD_ADDR_TYPE        (1)
+
 /************************************************************************************
 **  Local type definitions
 ************************************************************************************/
@@ -125,6 +130,8 @@
 static const char *BT_JNI_WORKQUEUE_NAME = "bt_jni_workqueue";
 static uid_set_t* uid_set = NULL;
 
+static BOOLEAN ssr_triggered = FALSE;
+
 /************************************************************************************
 **  Static functions
 ************************************************************************************/
@@ -170,17 +177,20 @@
 
 static void btif_context_switched(void *p_msg)
 {
-
-    BTIF_TRACE_VERBOSE("btif_context_switched");
-
     tBTIF_CONTEXT_SWITCH_CBACK *p = (tBTIF_CONTEXT_SWITCH_CBACK *) p_msg;
 
     /* each callback knows how to parse the data */
     if (p->p_cb)
+    {
+        BTIF_TRACE_VERBOSE("btif_context_switched for event: %u", p->event);
         p->p_cb(p->event, p->p_param);
+    }
+    else
+    {
+        BTIF_TRACE_ERROR("btif_context_switched with null callback");
+    }
 }
 
-
 /*******************************************************************************
 **
 ** Function         btif_transfer_context
@@ -328,6 +338,60 @@
     }
     return FALSE;
 }
+static bool fetch_vendor_addr (bt_bdaddr_t *local_addr)
+{
+    int addr_fd, i;
+    int bytes_read = 0;
+    bool status = false;
+    unsigned char payload[VENDOR_PAYLOAD_MAXLENGTH];
+    unsigned char header[VENDOR_MAX_CMD_HDR_SIZE];
+    char filename[NAME_MAX];
+
+    snprintf(filename, NAME_MAX, "%s/%s",VENDOR_PERSISTENCE_PATH,VENDOR_BT_NV_FILE_NAME);
+    BTIF_TRACE_VERBOSE("Opening file '%s' for reading\n",filename);
+
+    /* Open the Vendor BD Addr file */
+    addr_fd = open(filename, O_RDONLY);
+    if(addr_fd < 0)
+    {
+        BTIF_TRACE_ERROR("Open of Vendor BD addr file failed\n");
+        return false;
+    }
+
+    while((bytes_read = read(addr_fd, header, VENDOR_MAX_CMD_HDR_SIZE)) &&
+            (bytes_read == 0 || bytes_read == VENDOR_MAX_CMD_HDR_SIZE))
+    {
+        if( VENDOR_BD_ADDR_TYPE == header[0])
+        {
+            if(read(addr_fd, local_addr, header[2]) == header[2])
+            {
+                BTIF_TRACE_WARNING("Read the Vendor BD addr from '%s'\n",filename);
+                status = true;
+            }
+        }
+        else
+        {
+            if(read(addr_fd, payload, header[2]) == header[2])
+            {
+                continue;
+            }
+        }
+    }
+
+    if (status) // swap bd address
+    {
+        char swap;
+
+        for (i = 0 ; i < 3; i++) {
+            swap = local_addr->address[i];
+            local_addr->address[i] = local_addr->address[5-i];
+            local_addr->address[5-i] = swap;
+        }
+    }
+
+    close(addr_fd);
+    return status;
+}
 
 static void btif_fetch_local_bdaddr(bt_bdaddr_t *local_addr)
 {
@@ -380,6 +444,26 @@
         valid_bda = btif_fetch_property(FACTORY_BT_ADDR_PROPERTY, local_addr);
     }
 
+    /* No factory BDADDR found. Look for BDA in ro.boot.btmacaddr */
+    if ((!valid_bda) && \
+        (property_get("ro.boot.btmacaddr", val, NULL)))
+    {
+        valid_bda = string_to_bdaddr(val, local_addr);
+        if (valid_bda) {
+            BTIF_TRACE_DEBUG("Got vendor BDA %02X:%02X:%02X:%02X:%02X:%02X",
+                local_addr->address[0], local_addr->address[1], local_addr->address[2],
+                local_addr->address[3], local_addr->address[4], local_addr->address[5]);
+        }
+    }
+
+    if (!valid_bda && fetch_vendor_addr(local_addr))
+    {
+        valid_bda = TRUE;
+        BTIF_TRACE_DEBUG("Got Vendor BDA %02X:%02X:%02X:%02X:%02X:%02X",
+            local_addr->address[0], local_addr->address[1], local_addr->address[2],
+            local_addr->address[3], local_addr->address[4], local_addr->address[5]);
+    }
+
     /* Generate new BDA if necessary */
     if (!valid_bda)
     {
@@ -472,6 +556,8 @@
 
     BTIF_TRACE_DEBUG("%s: status %d, local bd [%s]", __FUNCTION__, status, bdstr);
 
+    ssr_triggered = FALSE;
+
     if (bdcmp(btif_local_bd_addr.address, controller->get_address()->address))
     {
         // TODO(zachoverflow): this whole code path seems like a bad time waiting to happen
@@ -521,12 +607,12 @@
         /* init rfcomm & l2cap api */
         btif_sock_init(uid_set);
 
-        /* init pan */
-        btif_pan_init();
-
         /* load did configuration */
         bte_load_did_conf(BTE_DID_CONF_FILE);
 
+        /* init pan */
+        btif_pan_init();
+
 #ifdef BTIF_DM_OOB_TEST
         btif_dm_load_local_oob();
 #endif
@@ -583,7 +669,11 @@
 void btif_disable_bluetooth_evt(void)
 {
     BTIF_TRACE_DEBUG("%s", __FUNCTION__);
-
+    if (ssr_triggered == TRUE)
+    {
+        BTIF_TRACE_DEBUG("%s SSR triggered,Ignore EVT",__FUNCTION__);
+        return;
+    }
 #if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE)
     bte_main_enable_lpm(FALSE);
 #endif
@@ -629,6 +719,62 @@
 }
 
 /*******************************************************************************
+Function       btif_ssrcleanup
+Description   Trigger SSR when Disable timeout occured
+
+*******************************************************************************/
+void btif_ssr_cleanup(void)
+{
+   BTIF_TRACE_DEBUG("%s", __FUNCTION__);
+   ssr_triggered = TRUE;
+   bte_ssr_cleanup(0x11);//SSR reason 0x11 - ENABLE_TIMEOUT
+}
+
+/*******************************************************************************
+**
+**   BTIF Test Mode APIs
+**
+*****************************************************************************/
+#if HCI_RAW_CMD_INCLUDED == TRUE
+/*******************************************************************************
+**
+** Function         btif_hci_event_cback
+**
+** Description     Callback invoked on receiving HCI event
+**
+** Returns          None
+**
+*******************************************************************************/
+static void btif_hci_event_cback ( tBTM_RAW_CMPL *p )
+{
+    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
+    if((p != NULL) && (bt_hal_cbacks != NULL)
+          && (bt_hal_cbacks->hci_event_recv_cb != NULL))
+    {
+        HAL_CBACK(bt_hal_cbacks, hci_event_recv_cb, p->event_code, p->p_param_buf,
+                                                                p->param_len);
+    }
+}
+
+/*******************************************************************************
+**
+** Function        btif_hci_cmd_send
+**
+** Description     Sends a HCI raw command to the controller
+**
+** Returns         BT_STATUS_SUCCESS on success
+**
+*******************************************************************************/
+bt_status_t btif_hci_cmd_send(uint16_t opcode, uint8_t *buf, uint8_t len)
+{
+    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
+
+    BTM_Hci_Raw_Command(opcode, len, buf, btif_hci_event_cback);
+    return BT_STATUS_SUCCESS;
+}
+#endif
+
+/*******************************************************************************
 **
 ** Function         btif_dut_mode_cback
 **
diff --git a/btif/src/btif_debug_conn.c b/btif/src/btif_debug_conn.c
index 9c9a9f3..cf9ac6d 100644
--- a/btif/src/btif_debug_conn.c
+++ b/btif/src/btif_debug_conn.c
@@ -42,9 +42,11 @@
   const time_t secs = ms / 1000;
   struct tm *ptm = localtime(&secs);
 
-  char tempbuff[20];
-  strftime(tempbuff, sizeof(tempbuff), "%m-%d %H:%M:%S", ptm);
-  snprintf(buffer, len, "%s.%03u", tempbuff, (uint16_t)(ms % 1000));
+  char tempbuff[20] = {0};
+  if (ptm) {
+    strftime(tempbuff, sizeof(tempbuff), "%m-%d %H:%M:%S", ptm);
+    snprintf(buffer, len, "%s.%03u", tempbuff, (uint16_t)(ms % 1000));
+  }
 
   return buffer;
 }
diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c
index f54b642..75cccde 100644
--- a/btif/src/btif_dm.c
+++ b/btif/src/btif_dm.c
@@ -64,6 +64,8 @@
 /******************************************************************************
 **  Constants & Macros
 ******************************************************************************/
+#define BTIF_DM_GET_REMOTE_PROP(b,t,v,l,p) \
+      {p.type=t;p.val=v;p.len=l;btif_storage_get_remote_device_property(b,&p);}
 
 #define COD_MASK                            0x07FF
 
@@ -167,11 +169,6 @@
     uint64_t energy_used;
 } btif_activity_energy_info_cb_t;
 
-typedef struct
-{
-    unsigned int   manufact_id;
-}skip_sdp_entry_t;
-
 typedef enum
 {
     BTIF_DM_FUNC_CREATE_BOND,
@@ -194,8 +191,6 @@
 
 #define MAX_BTIF_BOND_EVENT_ENTRIES 15
 
-static skip_sdp_entry_t sdp_blacklist[] = {{76}}; //Apple Mouse and Keyboard
-
 /* This flag will be true if HCI_Inquiry is in progress */
 static BOOLEAN btif_dm_inquiry_in_progress = FALSE;
 
@@ -221,6 +216,8 @@
 ******************************************************************************/
 static btif_dm_pairing_cb_t pairing_cb;
 static btif_dm_oob_cb_t     oob_cb;
+static UINT16 num_active_br_edr_links;
+static UINT16 num_active_le_links;
 static void btif_dm_generic_evt(UINT16 event, char* p_param);
 static void btif_dm_cb_create_bond(bt_bdaddr_t *bd_addr, tBTA_TRANSPORT transport);
 static void btif_dm_cb_hid_remote_name(tBTM_REMOTE_DEV_NAME *p_remote_name);
@@ -259,6 +256,9 @@
 extern bt_status_t btif_sdp_execute_service(BOOLEAN b_enable);
 extern int btif_hh_connect(bt_bdaddr_t *bd_addr);
 extern void bta_gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT16 uuid_16);
+extern void btif_av_move_idle(bt_bdaddr_t bd_addr);
+extern void btif_av_trigger_suspend();
+extern BOOLEAN btif_av_get_ongoing_multicast();
 
 /******************************************************************************
 **  Functions
@@ -351,6 +351,36 @@
     return BT_STATUS_SUCCESS;
 }
 
+
+/*******************************************************************************
+**
+** Function         check_eir_is_remote_name_short
+**
+** Description      Check if remote name is shortened
+**
+** Returns          TRUE if remote name found
+**                  else FALSE
+**
+*******************************************************************************/
+static BOOLEAN check_eir_is_remote_name_short(tBTA_DM_SEARCH *p_search_data)
+{
+    UINT8 *p_eir_remote_name = NULL;
+    UINT8 remote_name_len = 0;
+
+    /* Check EIR for remote name and services */
+    if (p_search_data->inq_res.p_eir)
+    {
+        p_eir_remote_name = BTM_CheckEirData(p_search_data->inq_res.p_eir,
+                BTM_EIR_SHORTENED_LOCAL_NAME_TYPE, &remote_name_len, p_search_data->inq_res.adv_data_len);
+
+        if (p_eir_remote_name)
+        {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
 /*******************************************************************************
 **
 ** Function         check_eir_remote_name
@@ -371,11 +401,11 @@
     if (p_search_data->inq_res.p_eir)
     {
         p_eir_remote_name = BTM_CheckEirData(p_search_data->inq_res.p_eir,
-                BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &remote_name_len);
+                BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &remote_name_len, p_search_data->inq_res.adv_data_len);
         if (!p_eir_remote_name)
         {
             p_eir_remote_name = BTM_CheckEirData(p_search_data->inq_res.p_eir,
-                    BTM_EIR_SHORTENED_LOCAL_NAME_TYPE, &remote_name_len);
+                    BTM_EIR_SHORTENED_LOCAL_NAME_TYPE, &remote_name_len, p_search_data->inq_res.adv_data_len);
         }
 
         if (p_eir_remote_name)
@@ -483,31 +513,97 @@
 
 /*****************************************************************************
 **
-** Function        check_sdp_bl
+** Function        interop_skip_authentication
 **
-** Description     Checks if a given device is blacklisted to skip sdp
+** Description     Checks if a given device is blacklisted to skip authentication
 **
-** Parameters     skip_sdp_entry
+** Parameters     remote_bdaddr
 **
 ** Returns         TRUE if the device is present in blacklist, else FALSE
 **
 *******************************************************************************/
-BOOLEAN check_sdp_bl(const bt_bdaddr_t *remote_bdaddr)
+static bool interop_skip_authentication(bt_bdaddr_t * remote_bdaddr)
 {
-    UINT16 manufacturer = 0;
-    UINT8 lmp_ver = 0;
-    UINT16 lmp_subver = 0;
+    if (remote_bdaddr == NULL)
+    {
+        LOG_WARN(LOG_TAG, "%s: remote_bdaddr = NULL, returning false", __func__);
+        return FALSE;
+    }
+
+    if (interop_match_addr(INTEROP_DISABLE_AUTH_FOR_HID_POINTING, remote_bdaddr))
+        return TRUE;
+
     bt_property_t prop_name;
-    bt_remote_version_t info;
+    bt_bdname_t bdname;
+
+    BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_BDNAME,
+                               sizeof(bt_bdname_t), &bdname);
+    if (btif_storage_get_remote_device_property((bt_bdaddr_t *)remote_bdaddr,
+                                              &prop_name) != BT_STATUS_SUCCESS)
+    {
+        LOG_WARN(LOG_TAG, "%s: BT_PROPERTY_BDNAME failed, returning false", __func__);
+        return FALSE;
+    }
+
+    if (strlen((const char *)bdname.name) != 0 &&
+        interop_match_name(INTEROP_DISABLE_SDP_AFTER_PAIRING, (const char *)bdname.name))
+        return TRUE;
+
+    return FALSE;
+}
+
+/*****************************************************************************
+**
+** Function        interop_skip_sdp
+**
+** Description     Checks if a given device is blacklisted to skip sdp
+**
+** Parameters     remote_bdaddr
+**
+** Returns         TRUE if the device is present in blacklist, else FALSE
+**
+*******************************************************************************/
+BOOLEAN interop_skip_sdp(const bt_bdaddr_t *remote_bdaddr)
+{
+    if (remote_bdaddr == NULL) {
+        LOG_WARN(LOG_TAG, "%s: remote_bdaddr = NULL, returning false", __func__);
+        return FALSE;
+    }
+
+    if (interop_match_addr(INTEROP_DISABLE_SDP_AFTER_PAIRING, remote_bdaddr)) {
+        LOG_WARN(LOG_TAG, "%s: device is in blacklist for skipping sdp", __func__);
+        return TRUE;
+    }
+
+    bt_property_t prop_name;
+    bt_bdname_t bdname;
+    BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_BDNAME,
+                               sizeof(bt_bdname_t), &bdname);
+    if (btif_storage_get_remote_device_property((bt_bdaddr_t *)remote_bdaddr,
+                                              &prop_name) != BT_STATUS_SUCCESS)
+    {
+        LOG_WARN(LOG_TAG, "%s: BT_PROPERTY_BDNAME failed, returning false", __func__);
+        return FALSE;
+    }
+
+    if (strlen((const char *)bdname.name) != 0 &&
+        interop_match_name(INTEROP_DISABLE_SDP_AFTER_PAIRING, (const char *)bdname.name))
+        return TRUE;
 
     if (remote_bdaddr == NULL)
         return FALSE;
 
-/* fetch additional info about remote device used in iop query */
+    UINT16 manufacturer = 0;
+    UINT8 lmp_ver = 0;
+    UINT16 lmp_subver = 0;
+
+    /* fetch additional info about remote device used in iop query */
     BTM_ReadRemoteVersion(*(BD_ADDR*)remote_bdaddr, &lmp_ver,
                     &manufacturer, &lmp_subver);
 
- /* if not available yet, try fetching from config database */
+    bt_remote_version_t info;
+
+    /* if not available yet, try fetching from config database */
     BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_REMOTE_VERSION_INFO,
                             sizeof(bt_remote_version_t), &info);
 
@@ -515,15 +611,15 @@
                                               &prop_name) != BT_STATUS_SUCCESS)
     {
 
+        APPL_TRACE_WARNING("%s: BT_PROPERTY_REMOTE_VERSION_INFO failed, returning false", __func__);
         return FALSE;
     }
     manufacturer = info.manufacturer;
 
-    for (unsigned int i = 0; i < ARRAY_SIZE(sdp_blacklist); i++)
-    {
-        if (manufacturer == sdp_blacklist[i].manufact_id)
-            return TRUE;
-    }
+    if (manufacturer != 0 &&
+        interop_match_manufacturer(INTEROP_DISABLE_SDP_AFTER_PAIRING, manufacturer))
+        return TRUE;
+
     return FALSE;
 }
 
@@ -550,13 +646,19 @@
                       state, pairing_cb.state, pairing_cb.sdp_attempts);
 
     HAL_CBACK(bt_hal_cbacks, bond_state_changed_cb, status, bd_addr, state);
-
     if (state == BT_BOND_STATE_BONDING)
     {
         pairing_cb.state = state;
         bdcpy(pairing_cb.bd_addr, bd_addr->address);
-    } else {
-        if (!pairing_cb.sdp_attempts)
+    } else if ((state == BT_BOND_STATE_NONE)&&
+        ((bdcmp(bd_addr->address, pairing_cb.bd_addr) == 0) ||
+        (bdcmp(bd_addr->address, pairing_cb.static_bdaddr.address) == 0)))
+    {
+        memset(&pairing_cb, 0, sizeof(pairing_cb));
+    }else{
+        if ((!pairing_cb.sdp_attempts)&&
+            ((bdcmp(bd_addr->address, pairing_cb.bd_addr) == 0) ||
+            (bdcmp(bd_addr->address, pairing_cb.static_bdaddr.address) == 0)))
             memset(&pairing_cb, 0, sizeof(pairing_cb));
         else
             BTIF_TRACE_DEBUG("%s: BR-EDR service discovery active", __func__);
@@ -768,6 +870,21 @@
 *******************************************************************************/
 void btif_dm_cb_remove_bond(bt_bdaddr_t *bd_addr)
 {
+     bt_bdname_t alias;
+     bt_property_t properties[1];
+     uint32_t num_properties = 0;
+     memset(&alias, 0, sizeof(alias));
+     BTIF_DM_GET_REMOTE_PROP(bd_addr, BT_PROPERTY_REMOTE_FRIENDLY_NAME,
+            &alias, sizeof(alias), properties[num_properties]);
+
+     if(alias.name[0] != '\0') {
+         properties[0].type = BT_PROPERTY_REMOTE_FRIENDLY_NAME;
+         properties[0].val = (void *) "";
+         properties[0].len = 1;
+
+         btif_storage_set_remote_device_property(bd_addr, &properties[0]);
+     }
+
      /*special handling for HID devices */
      /*  VUP needs to be sent if its a HID Device. The HID HOST module will check if there
      is a valid hid connection with this bd_addr. If yes VUP will be issued.*/
@@ -840,7 +957,7 @@
             if (p_src_data->inq_res.p_eir)
             {
                 p_dest_data->inq_res.p_eir = (UINT8 *)(p_dest + sizeof(tBTA_DM_SEARCH));
-                memcpy(p_dest_data->inq_res.p_eir, p_src_data->inq_res.p_eir, HCI_EXT_INQ_RESPONSE_LEN);
+                memcpy(p_dest_data->inq_res.p_eir, p_src_data->inq_res.p_eir, p_src_data->inq_res.adv_data_len);
             }
         }
         break;
@@ -919,6 +1036,14 @@
     bdcpy(bd_addr.address, p_pin_req->bd_addr);
     memcpy(bd_name.name, p_pin_req->bd_name, BD_NAME_LEN);
 
+    if (pairing_cb.state == BT_BOND_STATE_BONDING &&
+        bdcmp(bd_addr.address, pairing_cb.bd_addr) != 0)
+    {
+        BTIF_TRACE_WARNING("%s(): already in bonding state, reject request", __FUNCTION__);
+        btif_dm_pin_reply(&bd_addr, 0, 0, NULL);
+        return;
+    }
+
     bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING);
 
     cod = devclass2uint(p_pin_req->dev_class);
@@ -931,14 +1056,22 @@
     /* check for auto pair possiblity only if bond was initiated by local device */
     if (pairing_cb.is_local_initiated && (p_pin_req->min_16_digit == FALSE))
     {
+        if (bdcmp(pairing_cb.bd_addr, bd_addr.address))
+        {
+            /* Pin code from different device reject it as we dont support more than 1 pairing */
+            BTIF_TRACE_DEBUG("%s()rejecting pairing request", __FUNCTION__);
+            BTA_DmPinReply( (UINT8*)bd_addr.address, FALSE, 0, NULL);
+            return;
+        }
         if (check_cod(&bd_addr, COD_AV_HEADSETS) ||
             check_cod(&bd_addr, COD_AV_HEADPHONES) ||
+            check_cod(&bd_addr, COD_AV_HANDSFREE) ||
             check_cod(&bd_addr, COD_AV_PORTABLE_AUDIO) ||
             check_cod(&bd_addr, COD_AV_HIFI_AUDIO) ||
             check_cod(&bd_addr, COD_HID_POINTING))
         {
             /*  Check if this device can be auto paired  */
-            if (!interop_match_addr(INTEROP_DISABLE_AUTO_PAIRING, &bd_addr) &&
+            if (!interop_match_addr(INTEROP_DISABLE_AUTO_PAIRING, (bt_bdaddr_t *)&bd_addr) &&
                 !interop_match_name(INTEROP_DISABLE_AUTO_PAIRING, (const char *)bd_name.name) &&
                 (pairing_cb.autopair_attempts == 0))
             {
@@ -956,7 +1089,7 @@
         else if (check_cod(&bd_addr, COD_HID_KEYBOARD) ||
                  check_cod(&bd_addr, COD_HID_COMBO))
         {
-            if ((interop_match_addr(INTEROP_KEYBOARD_REQUIRES_FIXED_PIN, &bd_addr) == TRUE) &&
+            if ((interop_match_addr(INTEROP_KEYBOARD_REQUIRES_FIXED_PIN, (bt_bdaddr_t *)&bd_addr) == TRUE) &&
                 (pairing_cb.autopair_attempts == 0))
             {
                 BTIF_TRACE_DEBUG("%s() Attempting auto pair", __FUNCTION__);
@@ -1005,9 +1138,21 @@
     bdcpy(bd_addr.address, p_ssp_cfm_req->bd_addr);
     memcpy(bd_name.name, p_ssp_cfm_req->bd_name, BD_NAME_LEN);
 
+    if (pairing_cb.state == BT_BOND_STATE_BONDING &&
+        bdcmp(bd_addr.address, pairing_cb.bd_addr) != 0)
+    {
+        BTIF_TRACE_WARNING("%s(): already in bonding state, reject request", __FUNCTION__);
+        btif_dm_ssp_reply(&bd_addr, BT_SSP_VARIANT_PASSKEY_CONFIRMATION, 0, 0);
+        return;
+    }
+
     /* Set the pairing_cb based on the local & remote authentication requirements */
     bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING);
 
+    BTIF_TRACE_EVENT("%s: just_works :%d, loc_auth_req =%d, rmt_auth_req =%d ",
+        __FUNCTION__,p_ssp_cfm_req->just_works,p_ssp_cfm_req->loc_auth_req,
+        p_ssp_cfm_req->rmt_auth_req);
+
     /* if just_works and bonding bit is not set treat this as temporary */
     if (p_ssp_cfm_req->just_works && !(p_ssp_cfm_req->loc_auth_req & BTM_AUTH_BONDS) &&
         !(p_ssp_cfm_req->rmt_auth_req & BTM_AUTH_BONDS) &&
@@ -1036,6 +1181,19 @@
             BTIF_TRACE_EVENT("%s: User consent needed for incoming pairing request. loc_io_caps: %d, rmt_io_caps: %d",
                 __FUNCTION__, p_ssp_cfm_req->loc_io_caps, p_ssp_cfm_req->rmt_io_caps);
         }
+        /* Errata:4348
+         * Pairing confirmation for JustWorks needed if:
+         * 1. Outgoing (non-temporary) pairing is detected AND
+         * 2. local IO capabilities are DisplayYesNo AND
+         * 3. remote IO capbiltiies are NoInputNoOutput
+         */
+        else if (!is_incoming && pairing_cb.bond_type != BOND_TYPE_TEMPORARY &&
+                (p_ssp_cfm_req->loc_io_caps == HCI_IO_CAP_DISPLAY_YESNO) &&
+                (p_ssp_cfm_req->rmt_io_caps == HCI_IO_CAP_NO_IO))
+        {
+            BTIF_TRACE_EVENT("%s: Show pairing pop up for outgoing pairing when loc_io_caps: %d, rmt_io_caps: %d",
+                __FUNCTION__, p_ssp_cfm_req->loc_io_caps, p_ssp_cfm_req->rmt_io_caps);
+        }
         else
         {
             BTIF_TRACE_EVENT("%s: Auto-accept JustWorks pairing", __FUNCTION__);
@@ -1105,7 +1263,6 @@
     bt_bdaddr_t bd_addr;
     bt_status_t status = BT_STATUS_FAIL;
     bt_bond_state_t state = BT_BOND_STATE_NONE;
-    BOOLEAN skip_sdp = FALSE;
 
     BTIF_TRACE_DEBUG("%s: bond state=%d", __func__, pairing_cb.state);
 
@@ -1141,45 +1298,40 @@
         }
     }
 
-    // We could have received a new link key without going through the pairing flow.
-    // If so, we don't want to perform SDP or any other operations on the authenticated
-    // device.
-    if (bdcmp(p_auth_cmpl->bd_addr, pairing_cb.bd_addr) != 0) {
-      char address[32];
-      bt_bdaddr_t bt_bdaddr;
-
-      memcpy(bt_bdaddr.address, p_auth_cmpl->bd_addr,
-             sizeof(bt_bdaddr.address));
-      bdaddr_to_string(&bt_bdaddr, address, sizeof(address));
-      LOG_INFO(LOG_TAG, "%s skipping SDP since we did not initiate pairing to %s.", __func__, address);
-      return;
-    }
-
     // Skip SDP for certain  HID Devices
     if (p_auth_cmpl->success)
     {
+        // We could have received a new link key without going through the pairing flow.
+        // If so, we don't want to perform SDP or any other operations on the authenticated
+        // device. Also, make sure that the link key is not derived from secure LTK, because
+        // we will need to perform SDP in case of link key derivation to allow bond state change
+        // notification for the BR/EDR transport so that the subsequent BR/EDR connections
+        // to the remote can use the derived link key.
+        if ((bdcmp(p_auth_cmpl->bd_addr, pairing_cb.bd_addr) != 0) &&
+              (!pairing_cb.ble.is_penc_key_rcvd)) {
+            char address[32];
+            bt_bdaddr_t bt_bdaddr;
+
+            memcpy(bt_bdaddr.address, p_auth_cmpl->bd_addr,
+                  sizeof(bt_bdaddr.address));
+            bdaddr_to_string(&bt_bdaddr, address, sizeof(address));
+            LOG_INFO(LOG_TAG, "%s skipping SDP since we did not initiate pairing to %s.", __func__, address);
+            return;
+        }
 #if BLE_INCLUDED == TRUE
         btif_storage_set_remote_addr_type(&bd_addr, p_auth_cmpl->addr_type);
 #endif
         btif_update_remote_properties(p_auth_cmpl->bd_addr,
                                       p_auth_cmpl->bd_name, NULL, p_auth_cmpl->dev_type);
         pairing_cb.timeout_retries = 0;
-        status = BT_STATUS_SUCCESS;
-        state = BT_BOND_STATE_BONDED;
-        bdcpy(bd_addr.address, p_auth_cmpl->bd_addr);
 
-        if (check_sdp_bl(&bd_addr) && check_cod_hid(&bd_addr))
+        if (interop_skip_sdp(&bd_addr) && check_cod_hid(&bd_addr))
         {
-            LOG_WARN(LOG_TAG, "%s:skip SDP", __FUNCTION__);
-            skip_sdp = TRUE;
-        }
-        if(!pairing_cb.is_local_initiated && skip_sdp)
-        {
-            bond_state_changed(status, &bd_addr, state);
+            bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDED);
 
-            LOG_WARN(LOG_TAG, "%s: Incoming HID Connection",__FUNCTION__);
+            BTIF_TRACE_DEBUG("%s: HID Connection from "
+                "blacklisted device, skipping sdp",__FUNCTION__);
             bt_property_t prop;
-            bt_bdaddr_t bd_addr;
             bt_uuid_t  uuid;
             char uuid_str[128] = UUID_HUMAN_INTERFACE_DEVICE;
 
@@ -1189,12 +1341,18 @@
             prop.val = uuid.uu;
             prop.len = MAX_UUID_SIZE;
 
+            /* Also write this to the NVRAM */
+            status = btif_storage_set_remote_device_property(&bd_addr, &prop);
             /* Send the event to the BTIF */
             HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb,
                              BT_STATUS_SUCCESS, &bd_addr, 1, &prop);
         }
         else
         {
+            status = BT_STATUS_SUCCESS;
+            state = BT_BOND_STATE_BONDED;
+
+
 #if BLE_INCLUDED == TRUE
             BOOLEAN is_crosskey = FALSE;
             /* If bonded due to cross-key, save the static address too*/
@@ -1228,8 +1386,9 @@
         switch(p_auth_cmpl->fail_reason)
         {
             case HCI_ERR_PAGE_TIMEOUT:
-                if (interop_match_addr(INTEROP_AUTO_RETRY_PAIRING, &bd_addr)
-                    && pairing_cb.timeout_retries)
+                if ((pairing_cb.timeout_retries == NUM_TIMEOUT_RETRIES) ||
+                   (interop_match_addr(INTEROP_AUTO_RETRY_PAIRING, (bt_bdaddr_t *)&bd_addr)
+                    && pairing_cb.timeout_retries))
                 {
                     BTIF_TRACE_WARNING("%s() - Pairing timeout; retrying (%d) ...", __FUNCTION__, pairing_cb.timeout_retries);
                     --pairing_cb.timeout_retries;
@@ -1242,6 +1401,7 @@
                 break;
 
             case HCI_ERR_PAIRING_NOT_ALLOWED:
+                btif_storage_remove_bonded_device(&bd_addr);
                 status = BT_STATUS_AUTH_REJECTED;
                 break;
 
@@ -1249,9 +1409,12 @@
                 status =  BT_STATUS_AUTH_FAILURE;
                 break;
 
+            /* Dont fail the bonding for key missing error as stack retry security */
+            case HCI_ERR_KEY_MISSING:
+                btif_storage_remove_bonded_device(&bd_addr);
+                return;
             /* map the auth failure codes, so we can retry pairing if necessary */
             case HCI_ERR_AUTH_FAILURE:
-            case HCI_ERR_KEY_MISSING:
                 btif_storage_remove_bonded_device(&bd_addr);
             case HCI_ERR_HOST_REJECT_SECURITY:
             case HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE:
@@ -1260,6 +1423,7 @@
             case HCI_ERR_INSUFFCIENT_SECURITY:
             case HCI_ERR_PEER_USER:
             case HCI_ERR_UNSPECIFIED:
+            case HCI_ERR_REPEATED_ATTEMPTS:
                 BTIF_TRACE_DEBUG(" %s() Authentication fail reason %d",
                     __FUNCTION__, p_auth_cmpl->fail_reason);
                 if (pairing_cb.autopair_attempts  == 1)
@@ -1279,6 +1443,13 @@
             default:
                 status =  BT_STATUS_FAIL;
         }
+        if(p_auth_cmpl->fail_reason == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE
+                || p_auth_cmpl->fail_reason == HCI_ERR_UNIT_KEY_USED
+                || p_auth_cmpl->fail_reason == HCI_ERR_INSUFFCIENT_SECURITY
+                || p_auth_cmpl->fail_reason == HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED
+                || p_auth_cmpl->fail_reason == HCI_ERR_HOST_REJECT_SECURITY
+                || p_auth_cmpl->fail_reason == HCI_ERR_UNSPECIFIED)
+            GENERATE_VND_LOGS();
         /* Special Handling for HID Devices */
         if (check_cod(&bd_addr, COD_HID_POINTING)) {
             /* Remove Device as bonded in nvram as authentication failed */
@@ -1374,6 +1545,10 @@
                 uint32_t num_properties = 0;
                 bt_status_t status;
                 int addr_type = 0;
+                bt_bdname_t alias;
+                memset(&alias, 0, sizeof(alias));
+                BTIF_DM_GET_REMOTE_PROP(&bdaddr, BT_PROPERTY_REMOTE_FRIENDLY_NAME,
+                        &alias, sizeof(alias), properties[num_properties]);
 
                 memset(properties, 0, sizeof(properties));
                 /* BD_ADDR */
@@ -1382,13 +1557,28 @@
                 num_properties++;
                 /* BD_NAME */
                 /* Don't send BDNAME if it is empty */
-                if (bdname.name[0])
-                {
+                /* send alias name as the name if alias name present */
+                if(alias.name[0] != '\0') {
                     BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
                                                BT_PROPERTY_BDNAME,
-                                               strlen((char *)bdname.name), &bdname);
+                                               strlen((char *)alias.name), &alias);
                     num_properties++;
                 }
+                else if (bdname.name[0])
+                {
+                    if((check_eir_is_remote_name_short(p_search_data) == TRUE) &&
+                       (btif_storage_is_device_bonded(&bdaddr) == TRUE))
+                    {
+                        BTIF_TRACE_DEBUG("%s Don't update about the device name ", __FUNCTION__);
+                    }
+                    else
+                    {
+                        BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
+                                                 BT_PROPERTY_BDNAME,
+                                                strlen((char *)bdname.name), &bdname);
+                        num_properties++;
+                    }
+                }
 
                 /* DEV_CLASS */
                 BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
@@ -1495,8 +1685,9 @@
     {
         case BTA_DM_DISC_RES_EVT:
         {
-            bt_property_t prop;
             uint32_t i = 0;
+            bt_property_t prop[2];
+            int num_properties = 0;
             bt_bdaddr_t bd_addr;
             bt_status_t ret;
 
@@ -1513,12 +1704,12 @@
                 btif_dm_get_remote_services(&bd_addr);
                 return;
             }
-            prop.type = BT_PROPERTY_UUIDS;
-            prop.len = 0;
+            prop[0].type = BT_PROPERTY_UUIDS;
+            prop[0].len = 0;
             if ((p_data->disc_res.result == BTA_SUCCESS) && (p_data->disc_res.num_uuids > 0))
             {
-                 prop.val = p_data->disc_res.p_uuid_list;
-                 prop.len = p_data->disc_res.num_uuids * MAX_UUID_SIZE;
+                 prop[0].val = p_data->disc_res.p_uuid_list;
+                 prop[0].len = p_data->disc_res.num_uuids * MAX_UUID_SIZE;
                  for (i=0; i < p_data->disc_res.num_uuids; i++)
                  {
                       char temp[256];
@@ -1535,26 +1726,45 @@
                  (bdcmp(p_data->disc_res.bd_addr, pairing_cb.static_bdaddr.address) == 0)) &&
                   pairing_cb.sdp_attempts > 0)
             {
-                 BTIF_TRACE_DEBUG("%s Remote Service SDP done. Call bond_state_changed_cb BONDED",
-                                   __FUNCTION__);
-                 pairing_cb.sdp_attempts  = 0;
+                BTIF_TRACE_DEBUG("%s Remote Service SDP done. Call bond_state_changed_cb BONDED",
+                                __FUNCTION__);
+                if(p_data->disc_res.result != BTA_SUCCESS)
+                    GENERATE_VND_LOGS();
+                pairing_cb.sdp_attempts  = 0;
 
-                 // If bonding occured due to cross-key pairing, send bonding callback
-                 // for static address now
-                 if (bdcmp(p_data->disc_res.bd_addr, pairing_cb.static_bdaddr.address) == 0)
+                // If bonding occured due to cross-key pairing, send bonding callback
+                // for static address now
+                if (bdcmp(p_data->disc_res.bd_addr, pairing_cb.static_bdaddr.address) == 0)
                     bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING);
 
-                 bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDED);
+                bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDED);
             }
 
             if (p_data->disc_res.num_uuids != 0)
             {
                 /* Also write this to the NVRAM */
-                ret = btif_storage_set_remote_device_property(&bd_addr, &prop);
+                ret = btif_storage_set_remote_device_property(&bd_addr, &prop[0]);
                 ASSERTC(ret == BT_STATUS_SUCCESS, "storing remote services failed", ret);
+                num_properties++;
+            }
+
+            /* Remote name update */
+            if (strlen((const char *) p_data->disc_res.bd_name))
+            {
+                prop[1].type = BT_PROPERTY_BDNAME;
+                prop[1].val = p_data->disc_res.bd_name;
+                prop[1].len = strlen((char *)p_data->disc_res.bd_name);
+
+                ret = btif_storage_set_remote_device_property(&bd_addr, &prop[1]);
+                ASSERTC(ret == BT_STATUS_SUCCESS, "failed to save remote device property", ret);
+                num_properties++;
+            }
+
+            if(num_properties > 0)
+            {
                 /* Send the event to the BTIF */
                 HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb,
-                                 BT_STATUS_SUCCESS, &bd_addr, 1, &prop);
+                                 BT_STATUS_SUCCESS, &bd_addr, num_properties, prop);
             }
         }
         break;
@@ -1574,10 +1784,11 @@
              bt_uuid_t  uuid;
              int i = 0;
              int j = 15;
+             int num_properties = 0;
              if (p_data->disc_ble_res.service.uu.uuid16 == UUID_SERVCLASS_LE_HID)
              {
                 BTIF_TRACE_DEBUG("%s: Found HOGP UUID",__FUNCTION__);
-                bt_property_t prop;
+                bt_property_t prop[2];
                 bt_bdaddr_t bd_addr;
                 char temp[256];
                 bt_status_t ret;
@@ -1597,17 +1808,30 @@
                 LOG_INFO(LOG_TAG, "%s uuid:%s", __func__, temp);
 
                 bdcpy(bd_addr.address, p_data->disc_ble_res.bd_addr);
-                prop.type = BT_PROPERTY_UUIDS;
-                prop.val = uuid.uu;
-                prop.len = MAX_UUID_SIZE;
+                prop[0].type = BT_PROPERTY_UUIDS;
+                prop[0].val = uuid.uu;
+                prop[0].len = MAX_UUID_SIZE;
 
                 /* Also write this to the NVRAM */
-                ret = btif_storage_set_remote_device_property(&bd_addr, &prop);
+                ret = btif_storage_set_remote_device_property(&bd_addr, &prop[0]);
                 ASSERTC(ret == BT_STATUS_SUCCESS, "storing remote services failed", ret);
+                num_properties++;
+
+                /* Remote name update */
+                if (strnlen((const char *) p_data->disc_ble_res.bd_name, BD_NAME_LEN))
+                {
+                    prop[1].type = BT_PROPERTY_BDNAME;
+                    prop[1].val = p_data->disc_ble_res.bd_name;
+                    prop[1].len = strnlen((char *)p_data->disc_ble_res.bd_name, BD_NAME_LEN);
+
+                    ret = btif_storage_set_remote_device_property(&bd_addr, &prop[1]);
+                    ASSERTC(ret == BT_STATUS_SUCCESS, "failed to save remote device property", ret);
+                    num_properties++;
+                }
 
                 /* Send the event to the BTIF */
                 HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb,
-                                 BT_STATUS_SUCCESS, &bd_addr, 1, &prop);
+                                 BT_STATUS_SUCCESS, &bd_addr, num_properties, prop);
 
             }
         break;
@@ -1698,7 +1922,7 @@
              bt_status_t status;
              bt_property_t prop;
              prop.type = BT_PROPERTY_BDNAME;
-             prop.len = BD_NAME_LEN;
+             prop.len = BD_NAME_LEN + 1;
              prop.val = (void*)bdname;
 
              status = btif_storage_get_adapter_property(&prop);
@@ -1740,6 +1964,8 @@
              */
              btif_storage_load_bonded_devices();
 
+             load_iot_devlist(IOT_DEV_CONF_FILE);
+
              btif_enable_bluetooth_evt(p_data->enable.status);
         }
         break;
@@ -1748,14 +1974,12 @@
             /* for each of the enabled services in the mask, trigger the profile
              * disable */
             service_mask = btif_get_enabled_services_mask();
-            for (i=0; i <= BTA_MAX_SERVICE_ID; i++)
+            if (service_mask &
+                (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(BTA_BLE_SERVICE_ID)))
             {
-                if (service_mask &
-                    (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(i)))
-                {
-                    btif_in_execute_service_request(i, FALSE);
-                }
+                btif_in_execute_service_request(BTA_BLE_SERVICE_ID, FALSE);
             }
+            unload_iot_devlist();
             btif_disable_bluetooth_evt();
             break;
 
@@ -1773,6 +1997,7 @@
                 bdcpy(bd_addr.address, pairing_cb.bd_addr);
                 btm_set_bond_type_dev(pairing_cb.bd_addr, BOND_TYPE_UNKNOWN);
                 bond_state_changed(p_data->bond_cancel_cmpl.result, &bd_addr, BT_BOND_STATE_NONE);
+                btif_dm_remove_bond(&bd_addr);
             }
             break;
 
@@ -1823,6 +2048,33 @@
             bdcpy(bd_addr.address, p_data->link_up.bd_addr);
             BTIF_TRACE_DEBUG("BTA_DM_LINK_UP_EVT. Sending BT_ACL_STATE_CONNECTED");
 
+            if(p_data->link_up.link_type == BT_TRANSPORT_LE)
+            {
+                num_active_le_links++;
+                BTIF_TRACE_DEBUG("num_active_le_links is %d ",
+                    num_active_le_links);
+            }
+
+            if(p_data->link_up.link_type == BT_TRANSPORT_BR_EDR)
+            {
+                num_active_br_edr_links++;
+                BTIF_TRACE_DEBUG("num_active_br_edr_links is %d ",
+                    num_active_br_edr_links);
+            }
+            /* When tuchtones are enabled and 2 EDR HS are connected, if new
+             * connection is initated, then tuch tones are send to both connected HS
+             * over A2dp.Stream will be suspended after 3 secs and if remote has
+             * initiated play in this duartion, multicast must not be enabled with
+             * 3 ACL's, hence trigger a2dp suspend.
+             * During active muisc streaming no new connection can happen, hence
+             * We will get this only when multistreaming is happening due to tuchtones
+             */
+            if (btif_av_get_ongoing_multicast())
+            {
+                // trigger a2dp suspend
+                btif_av_trigger_suspend();
+            }
+
             btif_update_remote_version_property(&bd_addr);
 
             HAL_CBACK(bt_hal_cbacks, acl_state_changed_cb, BT_STATUS_SUCCESS,
@@ -1831,7 +2083,24 @@
 
         case BTA_DM_LINK_DOWN_EVT:
             bdcpy(bd_addr.address, p_data->link_down.bd_addr);
+
             btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN);
+
+            BTIF_TRACE_DEBUG("BTA_DM_LINK_DOWN_EVT. Sending BT_ACL_STATE_DISCONNECTED");
+            if (num_active_le_links > 0 &&
+                p_data->link_down.link_type == BT_TRANSPORT_LE)
+            {
+                num_active_le_links--;
+                BTIF_TRACE_DEBUG("num_active_le_links is %d ",num_active_le_links);
+            }
+
+            if (num_active_br_edr_links > 0 &&
+                p_data->link_down.link_type == BT_TRANSPORT_BR_EDR)
+            {
+                num_active_br_edr_links--;
+                BTIF_TRACE_DEBUG("num_active_br_edr_links is %d ",num_active_br_edr_links);
+            }
+            btif_av_move_idle(bd_addr);
             BTIF_TRACE_DEBUG("BTA_DM_LINK_DOWN_EVT. Sending BT_ACL_STATE_DISCONNECTED");
             HAL_CBACK(bt_hal_cbacks, acl_state_changed_cb, BT_STATUS_SUCCESS,
                       &bd_addr, BT_ACL_STATE_DISCONNECTED);
@@ -2078,7 +2347,9 @@
             }
             break;
         case BTIF_DM_CB_LE_TX_TEST:
+        case BTIF_DM_CB_LE_ENH_TX_TEST:
         case BTIF_DM_CB_LE_RX_TEST:
+        case BTIF_DM_CB_LE_ENH_RX_TEST:
             {
                 uint8_t status;
                 STREAM_TO_UINT8(status, p_param);
@@ -2145,14 +2416,14 @@
     {
         case BTA_DM_INQ_RES_EVT:
         {
-            if (p_data->inq_res.p_eir)
-                param_len += HCI_EXT_INQ_RESPONSE_LEN;
+            if (p_data && p_data->inq_res.p_eir)
+                param_len += p_data->inq_res.adv_data_len;
         }
         break;
 
         case BTA_DM_DISC_RES_EVT:
         {
-            if (p_data->disc_res.raw_data_size && p_data->disc_res.p_raw_data)
+            if (p_data && p_data->disc_res.raw_data_size && p_data->disc_res.p_raw_data)
                 param_len += p_data->disc_res.raw_data_size;
         }
         break;
@@ -2160,7 +2431,7 @@
     BTIF_TRACE_DEBUG("%s event=%s param_len=%d", __FUNCTION__, dump_dm_search_event(event), param_len);
 
     /* if remote name is available in EIR, set teh flag so that stack doesnt trigger RNR */
-    if (event == BTA_DM_INQ_RES_EVT)
+    if (p_data && event == BTA_DM_INQ_RES_EVT)
         p_data->inq_res.remt_name_not_required = check_eir_remote_name(p_data, NULL, NULL);
 
     btif_transfer_context (btif_dm_search_devices_evt , (UINT16) event, (void *)p_data, param_len,
@@ -2186,7 +2457,7 @@
    {
          case BTA_DM_DISC_RES_EVT:
          {
-             if ((p_data->disc_res.result == BTA_SUCCESS) && (p_data->disc_res.num_uuids > 0)) {
+             if ((p_data && p_data->disc_res.result == BTA_SUCCESS) && (p_data->disc_res.num_uuids > 0)) {
                   param_len += (p_data->disc_res.num_uuids * MAX_UUID_SIZE);
              }
          } break;
@@ -2290,7 +2561,11 @@
     tBTA_SERVICE_MASK services = 0;
     tBTA_DM_BLE_PF_FILT_PARAMS adv_filt_param;
 
-    BTIF_TRACE_EVENT("%s", __FUNCTION__);
+    BTIF_TRACE_EVENT("%s : pairing_cb.state: 0x%x", __FUNCTION__, pairing_cb.state);
+
+    /* We should not go for inquiry in BONDING STATE. */
+    if (pairing_cb.state == BT_BOND_STATE_BONDING)
+        return BT_STATUS_BUSY;
 
 #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
     memset(&adv_filt_param, 0, sizeof(tBTA_DM_BLE_PF_FILT_PARAMS));
@@ -2487,6 +2762,47 @@
 
 /*******************************************************************************
 **
+** Function         btif_dm_hh_open_success
+**
+** Description      informs the upper layers if the HH conneciton is successfully opened.
+**
+** Returns          none
+**
+*******************************************************************************/
+
+void btif_dm_hh_open_success(bt_bdaddr_t *bdaddr)
+{
+    if (pairing_cb.state != BT_BOND_STATE_BONDING ||
+            bdcmp(bdaddr->address, pairing_cb.bd_addr))
+        return;
+
+    if (interop_skip_authentication(bdaddr) && check_cod_hid(bdaddr))
+    {
+        bt_status_t status;
+        LINK_KEY link_key = {0};
+        bond_state_changed(BT_STATUS_SUCCESS, bdaddr, BT_BOND_STATE_BONDED);
+        BTIF_TRACE_DEBUG("%s: Device is blacklisted for authentication", __func__);
+        bt_property_t prop;
+        bt_uuid_t  uuid;
+        char uuid_str[128] = UUID_HUMAN_INTERFACE_DEVICE;
+        string_to_uuid(uuid_str, &uuid);
+        prop.type = BT_PROPERTY_UUIDS;
+        prop.val = uuid.uu;
+        prop.len = MAX_UUID_SIZE;
+        // Also write this to the NVRAM
+        status = btif_storage_set_remote_device_property(bdaddr, &prop);
+        ASSERTC(status == BT_STATUS_SUCCESS, "storing remote services failed", status);
+        // Store fake link for device as bonded in nvram,
+        // otherwise on device reboot/bt off-on device will not be shown in paired list.
+        btif_storage_add_bonded_device(bdaddr, link_key, HCI_LKEY_TYPE_UNAUTH_COMB, 0);
+        // Send the event to the BTIF
+        HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb,
+                         BT_STATUS_SUCCESS, bdaddr, 1, &prop);
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         btif_dm_hh_open_failed
 **
 ** Description      informs the upper layers if the HH have failed during bonding
@@ -2497,7 +2813,7 @@
 
 void btif_dm_hh_open_failed(bt_bdaddr_t *bdaddr)
 {
-    if (pairing_cb.state == BT_BOND_STATE_BONDING &&
+    if (check_cod_hid(bdaddr) && (pairing_cb.state == BT_BOND_STATE_BONDING) &&
             bdcmp(bdaddr->address, pairing_cb.bd_addr) == 0)
     {
         bond_state_changed(BT_STATUS_FAIL, bdaddr, BT_BOND_STATE_NONE);
@@ -2681,10 +2997,15 @@
 *******************************************************************************/
 bt_status_t btif_dm_get_remote_services(bt_bdaddr_t *remote_addr)
 {
-    bdstr_t bdstr;
+    bdstr_t bdstr = {'\0'};
 
     BTIF_TRACE_EVENT("%s: remote_addr=%s", __FUNCTION__, bdaddr_to_string(remote_addr, bdstr, sizeof(bdstr)));
 
+    if (bdaddr_is_empty(remote_addr))
+    {
+        BTIF_TRACE_WARNING("%s: remote_addr =%s not valid.", __FUNCTION__, bdaddr_to_string(remote_addr, bdstr, sizeof(bdstr)));
+        return BT_STATUS_FAIL;
+    }
     BTA_DmDiscover(remote_addr->address, BTA_ALL_SERVICE_MASK,
                    bte_dm_search_services_evt, TRUE);
 
@@ -3113,7 +3434,10 @@
         } else {
             btif_dm_save_ble_bonding_keys();
             BTA_GATTC_Refresh(bd_addr.address);
-            btif_dm_get_remote_services_by_transport(&bd_addr, BTA_GATT_TRANSPORT_LE);
+            if(!p_auth_cmpl->smp_over_br)
+               btif_dm_get_remote_services_by_transport(&bd_addr, BTA_GATT_TRANSPORT_LE);
+            else
+               btif_dm_get_remote_services(&bd_addr);
         }
     }
     else
@@ -3442,12 +3766,24 @@
                           (char *)p, 1, NULL);
 }
 
+static void btif_dm_ble_enh_tx_test_cback(void *p)
+{
+    btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_LE_ENH_TX_TEST,
+                          (char *)p, 1, NULL);
+}
+
 static void btif_dm_ble_rx_test_cback(void *p)
 {
     btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_LE_RX_TEST,
                           (char *)p, 1, NULL);
 }
 
+static void btif_dm_ble_enh_rx_test_cback(void *p)
+{
+    btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_LE_ENH_RX_TEST,
+                          (char *)p, 1, NULL);
+}
+
 static void btif_dm_ble_test_end_cback(void *p)
 {
     btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_LE_TEST_END,
@@ -3469,10 +3805,18 @@
              if (len != 3) return BT_STATUS_PARM_INVALID;
              BTM_BleTransmitterTest(buf[0],buf[1],buf[2], btif_dm_ble_tx_test_cback);
              break;
+         case HCI_BLE_ENH_TRANSMITTER_TEST:
+             if (len != 4) return BT_STATUS_PARM_INVALID;
+             BTM_BleEnhTransmitterTest(buf[0],buf[1],buf[2],buf[3], btif_dm_ble_enh_tx_test_cback);
+             break;
          case HCI_BLE_RECEIVER_TEST:
              if (len != 1) return BT_STATUS_PARM_INVALID;
              BTM_BleReceiverTest(buf[0], btif_dm_ble_rx_test_cback);
              break;
+         case HCI_BLE_ENH_RECEIVER_TEST:
+             if (len != 3) return BT_STATUS_PARM_INVALID;
+             BTM_BleEnhReceiverTest(buf[0],buf[1],buf[2], btif_dm_ble_enh_rx_test_cback);
+             break;
          case HCI_BLE_TEST_END:
              BTM_BleTestEnd((tBTM_CMPL_CB*) btif_dm_ble_test_end_cback);
              break;
@@ -3486,6 +3830,10 @@
 
 void btif_dm_on_disable()
 {
+    /* Cleanup static variables.*/
+    num_active_br_edr_links = 0;
+    num_active_le_links = 0;
+
     /* cancel any pending pairing requests */
     if (pairing_cb.state == BT_BOND_STATE_BONDING)
     {
@@ -3588,11 +3936,13 @@
         btif_bond_event_t* event = &btif_dm_bond_events[i];
 
         char eventtime[20];
-        char temptime[20];
+        char temptime[20] = {0};
         struct tm *tstamp = localtime(&event->timestamp.tv_sec);
-        strftime(temptime, sizeof(temptime), "%H:%M:%S", tstamp);
-        snprintf(eventtime, sizeof(eventtime), "%s.%03ld", temptime,
-                 event->timestamp.tv_nsec / 1000000);
+        if (tstamp) {
+            strftime(temptime, sizeof(temptime), "%H:%M:%S", tstamp);
+            snprintf(eventtime, sizeof(eventtime), "%s.%03ld", temptime,
+                     event->timestamp.tv_nsec / 1000000);
+        }
 
         char bdaddr[18];
         bdaddr_to_string(&event->bd_addr, bdaddr, sizeof(bdaddr));
@@ -3632,3 +3982,34 @@
     }
     pthread_mutex_unlock(&bond_event_lock);
 }
+
+/*******************************************************************************
+**
+** Function        btif_dm_get_br_edr_links.
+**
+** Description     Returns number of active BR/EDR links.
+**
+** Returns         UINT16
+**
+*******************************************************************************/
+UINT16 btif_dm_get_br_edr_links()
+{
+    BTIF_TRACE_DEBUG("BR/EDR Link count: %d", num_active_br_edr_links);
+    return num_active_br_edr_links;
+}
+
+/*******************************************************************************
+**
+** Function        btif_dm_get_le_links.
+**
+** Description     Returns number of active  LE links.
+**
+** Returns         UINT16
+**
+*******************************************************************************/
+UINT16 btif_dm_get_le_links()
+{
+    BTIF_TRACE_DEBUG("LE Link count: %d", num_active_le_links);
+    return num_active_le_links;
+}
+
diff --git a/btif/src/btif_gap.c b/btif/src/btif_gap.c
new file mode 100644
index 0000000..c90cc2d
--- /dev/null
+++ b/btif/src/btif_gap.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *        * Redistributions of source code must retain the above copyright
+ *          notice, this list of conditions and the following disclaimer.
+ *        * Redistributions in binary form must reproduce the above copyright
+ *            notice, this list of conditions and the following disclaimer in the
+ *            documentation and/or other materials provided with the distribution.
+ *        * Neither the name of The Linux Foundation nor
+ *            the names of its contributors may be used to endorse or promote
+ *            products derived from this software without specific prior written
+ *            permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.    IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <hardware/bluetooth.h>
+
+
+#define LOG_NDDEBUG 0
+#define LOG_TAG "bluedroid"
+
+#include "btif_api.h"
+#include "bt_utils.h"
+#include "gap_api.h"
+#include "l2c_api.h"
+
+#ifdef TEST_APP_INTERFACE
+#include <bt_testapp.h>
+
+
+
+static void GapAttrInit(void)
+{
+    GAP_Init();
+}
+static void Gap_BleAttrDBUpdate(BD_ADDR p_bda, UINT16 int_min, UINT16 int_max, UINT16 latency, UINT16 sp_tout)
+{
+    printf("%s:: remote_bd_addr=%02x:%02x:%02x:%02x:%02x:%02x, int_min=%d, int_max=%d, latency=%d sp_tout=%d\n", __FUNCTION__,
+            p_bda[0], p_bda[1], p_bda[2], p_bda[3], p_bda[4], p_bda[5],
+            int_min, int_max, latency, sp_tout);
+    L2CA_UpdateBleConnParams(p_bda, 50, 70, 0, 1000);
+
+}
+
+static const btgap_interface_t btgapInterface = {
+    sizeof(btgap_interface_t),
+    GapAttrInit,
+    Gap_BleAttrDBUpdate,
+};
+
+const btgap_interface_t *btif_gap_get_interface(void)
+{
+    BTIF_TRACE_EVENT("%s", __FUNCTION__);
+    return &btgapInterface;
+}
+
+#endif   //TEST_APP_INTERFACE
diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c
index 7ad4f08..bac5772 100644
--- a/btif/src/btif_gatt_client.c
+++ b/btif/src/btif_gatt_client.c
@@ -117,6 +117,10 @@
 #define ENABLE_BATCH_SCAN 1
 #define DISABLE_BATCH_SCAN 0
 
+#define SCAN_PHY_LE_1M    1
+#define SCAN_PHY_LE_CODED 4
+#define SCAN_PHY_LE_1M_CODED 5
+
 /*******************************************************************************
 **  Local type definitions
 ********************************************************************************/
@@ -199,9 +203,17 @@
     uint8_t     start;
     uint8_t     has_mask;
     int8_t      rssi;
+    uint8_t     scan_phys;
+    uint16_t    scan_interval_coded;
+    uint16_t    scan_window_coded;
+
+    uint16_t    duration;
+    uint16_t    period;
+
     uint8_t     flag;
     tBT_DEVICE_TYPE device_type;
     btgatt_transport_t transport;
+    UINT16      adv_data_len;
 } __attribute__((packed)) btif_gattc_cb_t;
 
 typedef struct
@@ -422,12 +434,12 @@
     bt_bdname_t bdname;
 
     p_eir_remote_name = BTM_CheckEirData(p_btif_cb->value,
-                                         BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &remote_name_len);
+                                         BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &remote_name_len, p_btif_cb->adv_data_len);
 
     if (p_eir_remote_name == NULL)
     {
         p_eir_remote_name = BTM_CheckEirData(p_btif_cb->value,
-                                BT_EIR_SHORTENED_LOCAL_NAME_TYPE, &remote_name_len);
+                                BT_EIR_SHORTENED_LOCAL_NAME_TYPE, &remote_name_len, p_btif_cb->adv_data_len);
     }
 
     if (p_eir_remote_name)
@@ -554,7 +566,9 @@
             }
 
             if (p_data->open.status == BTA_GATT_OK)
-                btif_gatt_check_encrypted_link(p_data->open.remote_bda, p_data->open.transport);
+#if (!defined(BTA_SKIP_BLE_START_ENCRYPTION) || BTA_SKIP_BLE_START_ENCRYPTION == FALSE)
+                btif_gatt_check_encrypted_link(p_data->open.remote_bda,p_data->open.transport);
+#endif
             break;
         }
 
@@ -584,12 +598,12 @@
             bt_property_t properties;
 
             p_eir_remote_name = BTM_CheckEirData(p_btif_cb->value,
-                                         BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &remote_name_len);
+                                                     BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &remote_name_len, p_btif_cb->adv_data_len);
 
             if (p_eir_remote_name == NULL)
             {
                 p_eir_remote_name = BTM_CheckEirData(p_btif_cb->value,
-                                BT_EIR_SHORTENED_LOCAL_NAME_TYPE, &remote_name_len);
+                                BT_EIR_SHORTENED_LOCAL_NAME_TYPE, &remote_name_len, p_btif_cb->adv_data_len);
             }
 
             if ((p_btif_cb->addr_type != BLE_ADDR_RANDOM) || (p_eir_remote_name))
@@ -665,6 +679,31 @@
             break;
         }
 
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+        case BTA_GATTC_EXTENDED_ADV_ENB_EVT:
+        {
+            btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*) p_param;
+            if (0xFF != p_btif_cb->inst_id)
+                btif_multi_adv_add_instid_map(p_btif_cb->client_if, p_btif_cb->inst_id, false);
+            HAL_CBACK(bt_gatt_callbacks, client->multi_adv_enable_cb
+                    , p_btif_cb->client_if
+                    , p_btif_cb->status
+                );
+            break;
+        }
+
+        case BTA_GATTC_EXTENDED_ADV_UPD_EVT:
+        {
+            btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*) p_param;
+            HAL_CBACK(bt_gatt_callbacks, client->multi_adv_update_cb
+                , p_btif_cb->client_if
+                , p_btif_cb->status
+            );
+            break;
+        }
+
+#endif
+
         case BTA_GATTC_MULT_ADV_DATA_EVT:
          {
             btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*) p_param;
@@ -862,6 +901,16 @@
             upevt = BTA_GATTC_MULT_ADV_DATA_EVT;
             break;
 
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+        case BTA_BLE_EXTENDED_ADV_ENB_EVT:
+            upevt = BTA_GATTC_EXTENDED_ADV_ENB_EVT;
+            break;
+
+        case BTA_BLE_EXTENDED_ADV_PARAM_EVT:
+            upevt = BTA_GATTC_EXTENDED_ADV_UPD_EVT;
+            break;
+#endif
+
         default:
             return;
     }
@@ -989,11 +1038,14 @@
             btif_cb.rssi = p_data->inq_res.rssi;
             btif_cb.addr_type = p_data->inq_res.ble_addr_type;
             btif_cb.flag = p_data->inq_res.flag;
+            btif_cb.adv_data_len = p_data->inq_res.adv_data_len;
+
+            memset(&btif_cb.value[0], 0, BTGATT_MAX_ATTR_LEN);
             if (p_data->inq_res.p_eir)
             {
-                memcpy(btif_cb.value, p_data->inq_res.p_eir, 62);
+                memcpy(btif_cb.value, p_data->inq_res.p_eir, p_data->inq_res.adv_data_len);
                 if (BTM_CheckEirData(p_data->inq_res.p_eir, BTM_EIR_COMPLETE_LOCAL_NAME_TYPE,
-                                      &len))
+                                                      &len, p_data->inq_res.adv_data_len))
                 {
                     p_data->inq_res.remt_name_not_required  = TRUE;
                 }
@@ -1115,6 +1167,10 @@
     tBT_UUID                   uuid;
     tBTA_GATT_UNFMT            descr_val;
 
+    if (!btif_is_enabled()) {
+       LOG_ERROR(LOG_TAG,"%s: bluetooth adapter not enabled",__FUNCTION__);
+       return;
+    }
     btif_gattc_cb_t* p_cb = (btif_gattc_cb_t*) p_param;
     if (!p_cb) return;
 
@@ -1136,11 +1192,11 @@
 
         case BTIF_GATTC_SCAN_START:
             btif_gattc_init_dev_cb();
-            BTA_DmBleObserve(TRUE, 0, bta_scan_results_cb);
+            BTA_DmBleObserve(TRUE, 0, 0, bta_scan_results_cb);
             break;
 
         case BTIF_GATTC_SCAN_STOP:
-            BTA_DmBleObserve(FALSE, 0, 0);
+            BTA_DmBleObserve(FALSE, 0, 0, 0);
             break;
 
         case BTIF_GATTC_OPEN:
@@ -1341,7 +1397,7 @@
                     cond.srvc_uuid.p_uuid_mask = NULL;
                     if (p_adv_filt_cb->has_mask)
                     {
-                        btif_to_bta_uuid_mask(&uuid_mask, &p_adv_filt_cb->uuid_mask);
+                        btif_to_bta_uuid_mask(&uuid_mask, &p_adv_filt_cb->uuid_mask, &p_adv_filt_cb->uuid);
                         cond.srvc_uuid.p_uuid_mask = &uuid_mask;
                     }
                     BTA_DmBleCfgFilterCondition(p_adv_filt_cb->action,
@@ -1516,10 +1572,12 @@
             {
                 btgatt_multi_adv_common_data *p_multi_adv_data_cb =
                     btif_obtain_multi_adv_data_cb();
+                p_multi_adv_data_cb->inst_cb[cbindex].frag_preference = p_adv_data->frag_preference;
                 BTA_BleCfgAdvInstData(
                     (UINT8)inst_id,
                     p_adv_data->set_scan_rsp,
                     p_multi_adv_data_cb->inst_cb[cbindex].mask,
+                    p_multi_adv_data_cb->inst_cb[cbindex].frag_preference,
                     &p_multi_adv_data_cb->inst_cb[cbindex].data);
             }
             else
@@ -1565,7 +1623,8 @@
 
         case BTIF_GATTC_SET_SCAN_PARAMS:
         {
-            BTA_DmSetBleScanParams(p_cb->client_if, p_cb->scan_interval, p_cb->scan_window,
+            BTA_DmSetBleScanParams(p_cb->client_if, p_cb->scan_phys, p_cb->scan_interval, p_cb->scan_window,
+                                   p_cb->scan_interval_coded, p_cb->scan_window_coded,
                                    BTM_BLE_SCAN_MODE_ACTI, bta_scan_param_setup_cb);
             break;
         }
@@ -1637,6 +1696,12 @@
 {
     CHECK_BTGATT_INIT();
     btif_gattc_cb_t btif_cb;
+
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    btif_cb.duration = 0;
+    btif_cb.period = 0;
+#endif
+
     return btif_transfer_context(btgattc_handle_event, start ? BTIF_GATTC_SCAN_START : BTIF_GATTC_SCAN_STOP,
                                  (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
 }
@@ -1989,9 +2054,23 @@
 {
     CHECK_BTGATT_INIT();
     btif_gattc_cb_t btif_cb;
+
+    memset(&btif_cb, 0, sizeof(btif_gattc_cb_t));
+
     btif_cb.client_if = client_if;
     btif_cb.scan_interval = scan_interval;
     btif_cb.scan_window = scan_window;
+
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    btif_cb.scan_phys = 0x01;/*LE 1M*/
+    btif_cb.scan_interval_coded = 0;
+    btif_cb.scan_window_coded = 0;
+
+    BTIF_TRACE_DEBUG("btif_gattc_set_scan_parameters ::scan_phys=%d scan_interval=%d scan_window= %d "
+                    "scan_interval_coded= %d scan_window_coded=%d",btif_cb.scan_phys,btif_cb.scan_interval,
+                    btif_cb.scan_window, btif_cb.scan_interval_coded, btif_cb.scan_window_coded);
+#endif
+
     return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SET_SCAN_PARAMS,
                                  (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
 }
@@ -2021,6 +2100,9 @@
     adv_cb.param.channel_map = chnl_map;
     adv_cb.param.adv_filter_policy = 0;
     adv_cb.param.tx_power = tx_power;
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    adv_cb.param.duration = timeout_s;
+#endif
     adv_cb.timeout_s = timeout_s;
     return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_ADV_INSTANCE_ENABLE,
                              (char*) &adv_cb, sizeof(btgatt_multi_adv_inst_cb), NULL);
@@ -2040,6 +2122,9 @@
     adv_cb.param.channel_map = chnl_map;
     adv_cb.param.adv_filter_policy = 0;
     adv_cb.param.tx_power = tx_power;
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    adv_cb.param.duration = timeout_s;
+#endif
     adv_cb.timeout_s = timeout_s;
     return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_ADV_INSTANCE_UPDATE,
                          (char*) &adv_cb, sizeof(btgatt_multi_adv_inst_cb), NULL);
@@ -2063,6 +2148,10 @@
         min_interval, max_interval, appearance, manufacturer_len, manufacturer_data,
         service_data_len, service_data, service_uuid_len, service_uuid, &multi_adv_data_inst);
 
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    multi_adv_data_inst.frag_preference = 0;
+#endif
+
     bt_status_t status = btif_transfer_context(
         btgattc_handle_event, BTIF_GATTC_ADV_INSTANCE_SET_DATA,
         (char *)&multi_adv_data_inst, sizeof(multi_adv_data_inst),
diff --git a/btif/src/btif_gatt_multi_adv_util.c b/btif/src/btif_gatt_multi_adv_util.c
index ddca7d2..8430475 100644
--- a/btif/src/btif_gatt_multi_adv_util.c
+++ b/btif/src/btif_gatt_multi_adv_util.c
@@ -43,6 +43,7 @@
 #include "btif_common.h"
 #include "btif_gatt_multi_adv_util.h"
 #include "btif_gatt_util.h"
+#include "device/include/controller.h"
 
 extern fixed_queue_t *btu_general_alarm_queue;
 
@@ -54,6 +55,11 @@
 
 btgatt_multi_adv_common_data *btif_obtain_multi_adv_data_cb()
 {
+    if (!controller_get_interface()->get_is_ready())
+    {
+        BTIF_TRACE_ERROR("btif_obtain_multi_adv_data_cb controller not ready!");
+        return NULL;
+    }
     int max_adv_inst = BTM_BleMaxMultiAdvInstanceCount();
     if (0 == max_adv_inst)
         max_adv_inst = 1;
diff --git a/btif/src/btif_gatt_qual.c b/btif/src/btif_gatt_qual.c
new file mode 100644
index 0000000..f973d67
--- /dev/null
+++ b/btif/src/btif_gatt_qual.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *        * Redistributions of source code must retain the above copyright
+ *          notice, this list of conditions and the following disclaimer.
+ *        * Redistributions in binary form must reproduce the above copyright
+ *            notice, this list of conditions and the following disclaimer in the
+ *            documentation and/or other materials provided with the distribution.
+ *        * Neither the name of The Linux Foundation nor
+ *            the names of its contributors may be used to endorse or promote
+ *            products derived from this software without specific prior written
+ *            permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.    IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <hardware/bluetooth.h>
+
+#define LOG_NDDEBUG 0
+#define LOG_TAG "bluedroid"
+
+#include "btif_api.h"
+#include "bt_utils.h"
+#include "gatt_api.h"
+#include "bta_api.h"
+
+#ifdef TEST_APP_INTERFACE
+#include <bt_testapp.h>
+
+UINT16    g_conn_id = 0;
+
+tGATT_IF Gatt_Register (tBT_UUID *p_app_uuid128, tGATT_CBACK *p_cb_info)
+{
+    tGATT_IF    Gatt_if = 0;
+    Gatt_if = GATT_Register (p_app_uuid128, p_cb_info);
+    printf("%s:: Gatt_if=%d\n", __FUNCTION__, Gatt_if);
+    if (!BTM_SetSecurityLevel (TRUE, "gatt_tool", /*BTM_SEC_SERVICE_SDP_SERVER*/ BTM_SEC_PROTO_L2CAP,
+                    0, 0x1f, 0, 0))
+        {
+        BTIF_TRACE_DEBUG("Error:: BTM_SetSecurityLevel failed");
+        return FALSE;
+    }
+    return Gatt_if;
+
+}
+void Gatt_Deregister (tGATT_IF gatt_if)
+{
+    GATT_Deregister (gatt_if);
+    printf("%s:: \n", __FUNCTION__);
+}
+
+void Gatt_StartIf(tGATT_IF gatt_if)
+{
+    GATT_StartIf (gatt_if);
+    printf("%s::\n", __FUNCTION__);
+}
+
+BOOLEAN Gatt_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct,tBT_TRANSPORT transport)
+{
+    BOOLEAN     Ret = 0;
+    Ret = GATT_Connect(gatt_if, bd_addr, is_direct,BT_TRANSPORT_LE, false);
+    printf("%s::Ret=%d,gatt_if=%d, is_direct=%d \n", __FUNCTION__, Ret, gatt_if, is_direct);
+    return Ret;
+}
+tGATT_STATUS Gatt_Disconnect (UINT16 conn_id)
+{
+    tGATT_STATUS Ret = 0;
+    Ret = GATT_Disconnect(conn_id);
+    printf("%s::Ret=%d,conn_id=%d\n", __FUNCTION__, Ret, conn_id);
+    return Ret;
+}
+
+BOOLEAN Gatt_Listen (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr)
+{
+    BOOLEAN Ret = 0;
+    Ret = GATT_Listen(gatt_if, start, bd_addr);
+    printf("%s::Ret=%d, gatt_if=%d, start=%d \n", __FUNCTION__, Ret, gatt_if, start);
+    return Ret;
+}
+    //GATT Client APIs
+    tGATT_STATUS Gatt_ConfigureMTU (UINT16 conn_id, UINT16  mtu)
+    {
+        tGATT_STATUS Ret =0;
+        Ret = GATTC_ConfigureMTU(conn_id, mtu);
+        printf("%s::Ret=%d, conn_id=%d, mtu=%d \n", __FUNCTION__, Ret, conn_id, mtu);
+        return Ret;
+    }
+
+    tGATT_STATUS Gatt_Discover (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_PARAM *p_param )
+    {
+        tGATT_STATUS Ret = 0;
+        Ret = GATTC_Discover(conn_id, disc_type, p_param);
+        printf("%s::Ret=%d, conn_id=%d, disc_type=%d \n", __FUNCTION__, Ret, conn_id, disc_type);
+        return Ret;
+    }
+
+    tGATT_STATUS Gatt_Read (UINT16 conn_id, tGATT_READ_TYPE type, tGATT_READ_PARAM *p_read)
+    {
+        tGATT_STATUS Ret = 0;
+        Ret = GATTC_Read(conn_id, type, p_read);
+        printf("%s::Ret=%d, conn_id=%d, type=%d \n", __FUNCTION__, Ret, conn_id, type);
+        return Ret;
+    }
+
+    tGATT_STATUS Gatt_Write (UINT16 conn_id, tGATT_WRITE_TYPE type, tGATT_VALUE *p_write)
+    {
+        tGATT_STATUS Ret = 0;
+        Ret = GATTC_Write(conn_id, type, p_write);
+        printf("%s::Ret=%d, conn_id=%d, type=%d \n", __FUNCTION__, Ret, conn_id, type);
+        return Ret;
+    }
+    tGATT_STATUS Gatt_ExecuteWrite (UINT16 conn_id, BOOLEAN is_execute)
+    {
+        tGATT_STATUS Ret = 0;
+        Ret = GATTC_ExecuteWrite(conn_id, is_execute);
+        printf("%s::Ret=%d, conn_id=%d, is_execute=%d \n", __FUNCTION__, Ret, conn_id, is_execute);
+        return Ret;
+    }
+    tGATT_STATUS Gatt_SendHandleValueConfirm (UINT16 conn_id, UINT16 handle)
+    {
+        tGATT_STATUS Ret = 0;
+        Ret = GATTC_SendHandleValueConfirm(conn_id, handle);
+        printf("%s::Ret=%d, conn_id=%d, handle=%d \n", __FUNCTION__, Ret, conn_id, handle);
+        return Ret;
+    }
+
+    void Gatt_SetIdleTimeout (BD_ADDR bd_addr, UINT16 idle_tout)
+    {
+        GATT_SetIdleTimeout (bd_addr, idle_tout,BT_TRANSPORT_LE);
+        printf("%s::\n", __FUNCTION__);
+    }
+
+    void Gatt_SetLeAdvMode (tBTA_DM_DISC disc_mode, tBTA_DM_CONN conn_mode)
+    {
+        printf("%s::call set Visibility\n", __FUNCTION__);
+        BTA_DmSetVisibility(disc_mode, conn_mode, BTA_DM_IGNORE, BTA_DM_IGNORE);
+    }
+
+static const btgatt_test_interface_t    btgatt_testInterface =
+{
+    sizeof(btgatt_test_interface_t),
+    Gatt_Register,
+    Gatt_Deregister,
+    Gatt_StartIf,
+    Gatt_Connect,
+    Gatt_Disconnect,
+    Gatt_Listen,
+    Gatt_ConfigureMTU,
+    Gatt_Discover,
+    Gatt_Read,
+    Gatt_Write,
+    Gatt_ExecuteWrite,
+    Gatt_SendHandleValueConfirm,
+    Gatt_SetIdleTimeout,
+    Gatt_SetLeAdvMode
+
+};
+
+
+const btgatt_test_interface_t *btif_gatt_test_get_interface(void)
+{
+    BTIF_TRACE_EVENT("%s", __FUNCTION__);
+    printf("\n%s\n", __FUNCTION__);
+    return &btgatt_testInterface;
+}
+
+#endif     //TEST_APP_INTERFACE
diff --git a/btif/src/btif_gatt_server.c b/btif/src/btif_gatt_server.c
index 4a4cc5b..039db8d 100644
--- a/btif/src/btif_gatt_server.c
+++ b/btif/src/btif_gatt_server.c
@@ -187,8 +187,9 @@
             bt_bdaddr_t bda;
             bdcpy(bda.address, p_data->conn.remote_bda);
 
-            btif_gatt_check_encrypted_link(p_data->conn.remote_bda, p_data->conn.transport);
-
+#if (!defined(BTA_SKIP_BLE_START_ENCRYPTION) || BTA_SKIP_BLE_START_ENCRYPTION == FALSE)
+            btif_gatt_check_encrypted_link(p_data->conn.remote_bda,p_data->conn.transport);
+#endif
             HAL_CBACK(bt_gatt_callbacks, server->connection_cb,
                       p_data->conn.conn_id, p_data->conn.server_if, TRUE, &bda);
             break;
@@ -358,6 +359,11 @@
 
 static void btgatts_handle_event(uint16_t event, char* p_param)
 {
+    if (!btif_is_enabled()) {
+       LOG_ERROR(LOG_TAG,"%s: bluetooth adapter not enabled",__FUNCTION__);
+       return;
+    }
+
     btif_gatts_cb_t* p_cb = (btif_gatts_cb_t*)p_param;
     if (!p_cb) return;
 
@@ -430,13 +436,15 @@
         }
 
         case BTIF_GATTS_CLOSE:
-            // Cancel pending foreground/background connections
-            BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, TRUE);
-            BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, FALSE);
 
             // Close active connection
             if (p_cb->conn_id != 0)
                 BTA_GATTS_Close(p_cb->conn_id);
+            else
+                BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, TRUE);
+
+            // Cancel pending background connections
+            BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, FALSE);
             break;
 
         case BTIF_GATTS_CREATE_SERVICE:
diff --git a/btif/src/btif_gatt_util.c b/btif/src/btif_gatt_util.c
index c93d866..17661ea 100644
--- a/btif/src/btif_gatt_util.c
+++ b/btif/src/btif_gatt_util.c
@@ -118,20 +118,21 @@
     memcpy(p_dest->attr_value.value, p_src->attr_value.value, GATT_MAX_ATTR_LEN);
 }
 
-void btif_to_bta_uuid_mask(tBTA_DM_BLE_PF_COND_MASK *p_mask, bt_uuid_t *p_src)
+void btif_to_bta_uuid_mask(tBTA_DM_BLE_PF_COND_MASK *p_mask, bt_uuid_t *uuid_mask, bt_uuid_t *svc_uuid)
 {
-    char *p_byte = (char*)p_src;
+    char *p_byte = (char*)uuid_mask;
+    int uuid_len = uuidType(svc_uuid->uu);
     int i = 0;
 
-    switch (uuidType(p_src->uu))
+    switch (uuid_len)
     {
         case LEN_UUID_16:
-            p_mask->uuid16_mask = (p_src->uu[13] << 8) + p_src->uu[12];
+            p_mask->uuid16_mask = (uuid_mask->uu[13] << 8) + uuid_mask->uu[12];
             break;
 
         case LEN_UUID_32:
-            p_mask->uuid32_mask = (p_src->uu[13] <<  8) + p_src->uu[12];
-            p_mask->uuid32_mask += (p_src->uu[15] << 24) + (p_src->uu[14] << 16);
+            p_mask->uuid32_mask = (uuid_mask->uu[13] <<  8) + uuid_mask->uu[12];
+            p_mask->uuid32_mask += (uuid_mask->uu[15] << 24) + (uuid_mask->uu[14] << 16);
             break;
 
         case LEN_UUID_128:
diff --git a/btif/src/btif_hf.c b/btif/src/btif_hf.c
index 9d963d1..9883f42 100644
--- a/btif/src/btif_hf.c
+++ b/btif/src/btif_hf.c
@@ -30,6 +30,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
+#include <cutils/properties.h>
 
 #include <hardware/bluetooth.h>
 #include <hardware/bt_hf.h>
@@ -40,6 +41,7 @@
 #include "btif_common.h"
 #include "btif_profile_queue.h"
 #include "btif_util.h"
+#include "device/include/controller.h"
 
 /************************************************************************************
 **  Constants & Macros
@@ -64,7 +66,6 @@
 #define BTIF_HF_SECURITY    (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)
 #endif
 
-#if (BTM_WBS_INCLUDED == TRUE )
 #ifndef BTIF_HF_FEATURES
 #define BTIF_HF_FEATURES   ( BTA_AG_FEAT_3WAY | \
                              BTA_AG_FEAT_ECNR   | \
@@ -73,25 +74,10 @@
                              BTA_AG_FEAT_EXTERR | \
                              BTA_AG_FEAT_BTRH   | \
                              BTA_AG_FEAT_VREC   | \
-                             BTA_AG_FEAT_CODEC |\
-                             BTA_AG_FEAT_HF_IND | \
-                             BTA_AG_FEAT_ESCO   | \
+                             BTA_AG_FEAT_HFIND  | \
+                             BTA_AG_FEAT_S4     | \
                              BTA_AG_FEAT_UNAT)
 #endif
-#else
-#ifndef BTIF_HF_FEATURES
-#define BTIF_HF_FEATURES   ( BTA_AG_FEAT_3WAY | \
-                             BTA_AG_FEAT_ECNR   | \
-                             BTA_AG_FEAT_REJECT | \
-                             BTA_AG_FEAT_ECS    | \
-                             BTA_AG_FEAT_EXTERR | \
-                             BTA_AG_FEAT_BTRH   | \
-                             BTA_AG_FEAT_VREC   | \
-                             BTA_AG_FEAT_HF_IND | \
-                             BTA_AG_FEAT_ESCO   | \
-                             BTA_AG_FEAT_UNAT)
-#endif
-#endif
 
 #define BTIF_HF_CALL_END_TIMEOUT       6
 
@@ -100,6 +86,9 @@
 /* Number of BTIF-HF control blocks */
 #define BTIF_HF_NUM_CB       2
 
+/* Assigned number for mSBC codec */
+#define BTA_AG_MSBC_CODEC 5
+
 /* Max HF clients supported from App */
 UINT16 btif_max_hf_clients = 1;
 
@@ -127,6 +116,7 @@
 ************************************************************************************/
 static bthf_callbacks_t *bt_hf_callbacks = NULL;
 static int hf_idx = BTIF_HF_INVALID_IDX;
+static UINT32 btif_features = BTIF_HF_FEATURES;
 
 #define CHECK_BTHF_INIT() if (bt_hf_callbacks == NULL)\
     {\
@@ -135,7 +125,7 @@
     }\
     else\
     {\
-        BTIF_TRACE_EVENT("BTHF: %s", __FUNCTION__);\
+        BTIF_TRACE_IMP("BTHF: %s", __FUNCTION__);\
     }
 
 #define CHECK_BTHF_SLC_CONNECTED() if (bt_hf_callbacks == NULL)\
@@ -166,6 +156,7 @@
     struct timespec         call_end_timestamp;
     struct timespec         connected_timestamp;
     bthf_call_state_t       call_setup_state;
+    bthf_audio_state_t      audio_state;
 } btif_hf_cb_t;
 
 static btif_hf_cb_t btif_hf_cb[BTIF_HF_NUM_CB];
@@ -181,10 +172,12 @@
 * codec unless this variable is set to TRUE.
 */
 #ifndef BTIF_HF_WBS_PREFERRED
-#define BTIF_HF_WBS_PREFERRED   FALSE
+#define BTIF_HF_WBS_PREFERRED  TRUE
 #endif
 
 BOOLEAN btif_conf_hf_force_wbs = BTIF_HF_WBS_PREFERRED;
+BOOLEAN send_bvra_other_index = FALSE;
+int bvra_other_index_state  = 0;
 
 /************************************************************************************
 **  Functions
@@ -215,6 +208,88 @@
 
 /*******************************************************************************
 **
+** Function         btif_hf_is_connected_on_other_idx
+**
+** Description      Checks if any other AV SCB is connected
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+
+BOOLEAN btif_hf_is_connected_on_other_idx(int current_index)
+{
+    int i;
+    for (i = 0; i < btif_max_hf_clients; i++)
+    {
+        if (i != current_index)
+        {
+            if ((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
+                 (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED))
+                return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         btif_hf_get_other_connected_index
+**
+** Description      Checks for other connected index
+**
+** Returns          Other connected index
+**
+*******************************************************************************/
+
+int btif_hf_get_other_connected_index(int current_index)
+{
+    int i;
+    for (i = 0; i < btif_max_hf_clients; i++)
+    {
+        if (i != current_index)
+        {
+            if ((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
+                 (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED))
+                return i;
+        }
+    }
+    return btif_max_hf_clients;
+}
+/*******************************************************************************
+**
+** Function         send_bvra_update
+**
+** Description      Internal function to updated other connected HS for BVRA state
+**
+** Returns          void
+**
+*******************************************************************************/
+static void send_bvra_update(int index)
+{
+    BTIF_TRACE_EVENT("connected %d",btif_hf_is_connected_on_other_idx(index));
+    if (btif_hf_is_connected_on_other_idx(index))
+    {
+        int other_idx = btif_hf_get_other_connected_index(index);
+        BTIF_TRACE_EVENT("other_idx %d",other_idx);
+        if (other_idx < btif_max_hf_clients &&
+                (btif_hf_cb[other_idx].peer_feat & BTA_AG_PEER_FEAT_VREC))
+        {
+            tBTA_AG_RES_DATA ag_res;
+            memset(&ag_res, 0, sizeof(ag_res));
+            ag_res.state = bvra_other_index_state;
+            BTIF_TRACE_EVENT("sending on idex %d",other_idx);
+            BTA_AgResult (btif_hf_cb[other_idx].handle,
+                    BTA_AG_BVRA_RES, &ag_res);
+        }
+        else
+        {
+            BTIF_TRACE_EVENT("Invalid connected index");
+        }
+    }
+
+}
+/*******************************************************************************
+**
 ** Function         btif_hf_idx_by_bdaddr
 **
 ** Description      Internal function to get idx by bdaddr
@@ -227,7 +302,7 @@
         int i;
         for (i = 0; i < btif_max_hf_clients; ++i)
         {
-            if ((bdcmp(bd_addr->address,
+            if (is_connected(bd_addr) && (bdcmp(bd_addr->address,
                                   btif_hf_cb[i].connected_bda.address) == 0))
                 return i;
         }
@@ -371,6 +446,40 @@
     }
 }
 
+/*******************************************************************************
+**
+** Function         btif_hf_check_if_sco_connected
+**
+** Description      Returns BT_STATUS_SUCCESS if SCO is up for any HF
+**
+** Returns          bt_status_t
+**
+*******************************************************************************/
+static bt_status_t btif_hf_check_if_sco_connected()
+{
+    if (bt_hf_callbacks == NULL)
+    {
+        BTIF_TRACE_WARNING("BTHF: %s: BTHF not initialized. ", __FUNCTION__);
+        return BT_STATUS_NOT_READY;
+    }
+    else
+    {
+        int i;
+        for (i = 0; i < btif_max_hf_clients; i++)
+        {
+            if ((btif_hf_cb[i].audio_state == BTHF_AUDIO_STATE_CONNECTED) ||
+                (btif_hf_cb[i].audio_state == BTHF_AUDIO_STATE_CONNECTING))
+            {
+                BTIF_TRACE_EVENT("BTHF: %s: sco connected/connecting for idx = %d",
+                                         __FUNCTION__, i);
+                return BT_STATUS_SUCCESS;
+            }
+        }
+        BTIF_TRACE_WARNING("BTHF: %s: No SCO connection up", __FUNCTION__);
+        return BT_STATUS_NOT_READY;
+    }
+}
+
 /*****************************************************************************
 **   Section name (Group of functions)
 *****************************************************************************/
@@ -394,10 +503,23 @@
 {
     tBTA_AG *p_data = (tBTA_AG *)p_param;
     bdstr_t bdstr;
-    int idx = p_data->hdr.handle - 1;
+    int idx;
+    BOOLEAN ignore_rfc_fail = false;
 
-    BTIF_TRACE_DEBUG("%s: event=%s", __FUNCTION__, dump_hf_event(event));
+    BTIF_TRACE_IMP("%s: event=%s", __FUNCTION__, dump_hf_event(event));
 
+    // for BTA_AG_ENABLE_EVT/BTA_AG_DISABLE_EVT, p_data is NULL
+    if (event == BTA_AG_ENABLE_EVT || event == BTA_AG_DISABLE_EVT)
+        return;
+
+    // p_data is NULL for any other event, return
+    if (p_data == NULL)
+    {
+        BTIF_TRACE_ERROR("%s: data is NULL", __FUNCTION__);
+        return;
+    }
+
+    idx = p_data->hdr.handle - 1;
     if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
     {
         BTIF_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
@@ -406,10 +528,6 @@
 
     switch (event)
     {
-        case BTA_AG_ENABLE_EVT:
-        case BTA_AG_DISABLE_EVT:
-            break;
-
         case BTA_AG_REGISTER_EVT:
             btif_hf_cb[idx].handle = p_data->reg.hdr.handle;
             BTIF_TRACE_DEBUG("%s: BTA_AG_REGISTER_EVT,"
@@ -427,6 +545,18 @@
             }
             else if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_CONNECTING)
             {
+                /* In Multi-hf, if outgoing RFCOMM connection fails due to collision,
+                 * ignore the failure if HF is already connected.
+                 */
+                if ( (btif_max_hf_clients > 1) &&
+                     (p_data->open.status == BTA_AG_FAIL_RFCOMM) &&
+                     (is_connected(&btif_hf_cb[idx].connected_bda)) )
+                {
+                     BTIF_TRACE_WARNING("%s: Ignoring RFCOMM failure due to collision for dev %s",
+                          __FUNCTION__, bdaddr_to_string(&btif_hf_cb[idx].connected_bda, bdstr, sizeof(bdstr)));
+                     ignore_rfc_fail = true;
+                }
+
                 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
             }
             else
@@ -437,19 +567,25 @@
                 break;
             }
 
-            HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
+            if (ignore_rfc_fail != true)
+            {
+                HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
                                                         &btif_hf_cb[idx].connected_bda);
+            }
 
             if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_DISCONNECTED)
                 bdsetany(btif_hf_cb[idx].connected_bda.address);
 
-            if (p_data->open.status != BTA_AG_SUCCESS)
-                btif_queue_advance();
+            btif_queue_advance();
+
             break;
 
         case BTA_AG_CLOSE_EVT:
             btif_hf_cb[idx].connected_timestamp.tv_sec = 0;
             btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
+
+            BTIF_TRACE_IMP("%s: Moving the audio_state to DISCONNECTED", __FUNCTION__);
+            btif_hf_cb[idx].audio_state = BTHF_AUDIO_STATE_DISCONNECTED;
             BTIF_TRACE_DEBUG("%s: BTA_AG_CLOSE_EVT,"
                  "idx = %d, btif_hf_cb.handle = %d", __FUNCTION__, idx,
                           btif_hf_cb[idx].handle);
@@ -476,16 +612,19 @@
 
             HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
                              &btif_hf_cb[idx].connected_bda);
-            btif_queue_advance();
             break;
 
         case BTA_AG_AUDIO_OPEN_EVT:
             hf_idx = idx;
+            BTIF_TRACE_IMP("%s: Moving the audio_state to CONNECTED", __FUNCTION__);
+            btif_hf_cb[idx].audio_state = BTHF_AUDIO_STATE_CONNECTED;
             HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTED,
                                                         &btif_hf_cb[idx].connected_bda);
             break;
 
         case BTA_AG_AUDIO_CLOSE_EVT:
+            BTIF_TRACE_IMP("%s: Moving the audio_state to DISCONNECTED", __FUNCTION__);
+            btif_hf_cb[idx].audio_state = BTHF_AUDIO_STATE_DISCONNECTED;
             HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_DISCONNECTED,
                                                            &btif_hf_cb[idx].connected_bda);
             break;
@@ -541,6 +680,9 @@
             HAL_CBACK(bt_hf_callbacks, vr_cmd_cb,
                 (p_data->val.num == 1) ? BTHF_VR_STATE_STARTED :
                       BTHF_VR_STATE_STOPPED, &btif_hf_cb[idx].connected_bda);
+            send_bvra_other_index = TRUE;
+            bvra_other_index_state = p_data->val.num;
+
             break;
 
         case BTA_AG_AT_NREC_EVT:
@@ -627,19 +769,26 @@
             break;
 
         case BTA_AG_AT_BIND_EVT:
-            if (p_data->val.hdr.status == BTA_AG_SUCCESS)
+            switch(p_data->val.num)
             {
-                HAL_CBACK(bt_hf_callbacks, bind_cb,p_data->val.str,
-                                                &btif_hf_cb[idx].connected_bda);
+                case BTA_AG_AT_SET:
+                    HAL_CBACK(bt_hf_callbacks, bind_cmd_cb, p_data->val.str, BTHF_BIND_SET,
+                                               &btif_hf_cb[idx].connected_bda);
+                    break;
+                case BTA_AG_AT_READ:
+                    HAL_CBACK(bt_hf_callbacks, bind_cmd_cb, p_data->val.str, BTHF_BIND_READ,
+                                               &btif_hf_cb[idx].connected_bda);
+                    break;
+                case BTA_AG_AT_TEST:
+                    HAL_CBACK(bt_hf_callbacks, bind_cmd_cb, p_data->val.str, BTHF_BIND_TEST,
+                                               &btif_hf_cb[idx].connected_bda);
+                    break;
             }
             break;
-
         case BTA_AG_AT_BIEV_EVT:
-            if (p_data->val.hdr.status == BTA_AG_SUCCESS)
-            {
-                HAL_CBACK(bt_hf_callbacks, biev_cb, (bthf_hf_ind_type_t)p_data->val.lidx, (int)p_data->val.num,
-                              &btif_hf_cb[idx].connected_bda);
-            }
+            HAL_CBACK(bt_hf_callbacks, biev_cmd_cb, p_data->val.str,
+                                               &btif_hf_cb[idx].connected_bda);
+
             break;
         default:
             BTIF_TRACE_WARNING("%s: Unhandled event: %d", __FUNCTION__, event);
@@ -706,6 +855,8 @@
     switch (event) {
         case BTIF_HFP_CB_AUDIO_CONNECTING:
         {
+            BTIF_TRACE_IMP("%s: Moving the audio_state to CONNECTING", __FUNCTION__);
+            btif_hf_cb[idx].audio_state = BTHF_AUDIO_STATE_CONNECTING;
             HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTING,
                       &btif_hf_cb[idx].connected_bda);
         } break;
@@ -815,7 +966,7 @@
         return BT_STATUS_FAIL;
     }
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         BTA_AgClose(btif_hf_cb[idx].handle);
         return BT_STATUS_SUCCESS;
@@ -849,7 +1000,7 @@
     if (btif_hf_check_if_slc_connected() != BT_STATUS_SUCCESS)
         return BT_STATUS_NOT_READY;
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         BTA_AgAudioOpen(btif_hf_cb[idx].handle);
 
@@ -883,7 +1034,7 @@
         return BT_STATUS_FAIL;
     }
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         BTA_AgAudioClose(btif_hf_cb[idx].handle);
         return BT_STATUS_SUCCESS;
@@ -904,33 +1055,29 @@
 static bt_status_t start_voice_recognition(bt_bdaddr_t *bd_addr)
 {
     CHECK_BTHF_INIT();
-
-    int idx = btif_hf_idx_by_bdaddr(bd_addr);
-
-    if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
+    BOOLEAN is_success = FALSE;
+    for (int i = 0; i < btif_max_hf_clients; i++)
     {
-        BTIF_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
-        return BT_STATUS_FAIL;
-    }
-
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
-    {
-        if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC)
+        if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
+                (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)) &&
+                btif_hf_cb[i].peer_feat & BTA_AG_PEER_FEAT_VREC)
         {
             tBTA_AG_RES_DATA ag_res;
             memset(&ag_res, 0, sizeof(ag_res));
             ag_res.state = 1;
-            BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
-
-            return BT_STATUS_SUCCESS;
-        }
-        else
-        {
-            return BT_STATUS_UNSUPPORTED;
+            BTA_AgResult (btif_hf_cb[i].handle, BTA_AG_BVRA_RES, &ag_res);
+            is_success = TRUE;
         }
     }
 
-    return BT_STATUS_NOT_READY;
+    if (is_success)
+    {
+        return BT_STATUS_SUCCESS;
+    }
+    else
+    {
+        return BT_STATUS_NOT_READY;
+    }
 }
 
 /*******************************************************************************
@@ -945,33 +1092,29 @@
 static bt_status_t stop_voice_recognition(bt_bdaddr_t *bd_addr)
 {
     CHECK_BTHF_INIT();
-
-    int idx = btif_hf_idx_by_bdaddr(bd_addr);
-
-    if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
+    BOOLEAN is_success = FALSE;
+    for (int i = 0; i < btif_max_hf_clients; i++)
     {
-        BTIF_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
-        return BT_STATUS_FAIL;
-    }
-
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
-    {
-        if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC)
+        if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
+                (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)) &&
+                btif_hf_cb[i].peer_feat & BTA_AG_PEER_FEAT_VREC)
         {
             tBTA_AG_RES_DATA ag_res;
             memset(&ag_res, 0, sizeof(ag_res));
             ag_res.state = 0;
-            BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
-
-            return BT_STATUS_SUCCESS;
-        }
-        else
-        {
-            return BT_STATUS_UNSUPPORTED;
+            BTA_AgResult (btif_hf_cb[i].handle, BTA_AG_BVRA_RES, &ag_res);
+            is_success = TRUE;
         }
     }
 
-    return BT_STATUS_NOT_READY;
+    if (is_success)
+    {
+        return BT_STATUS_SUCCESS;
+    }
+    else
+    {
+        return BT_STATUS_NOT_READY;
+    }
 }
 
 /*******************************************************************************
@@ -998,7 +1141,7 @@
 
     tBTA_AG_RES_DATA ag_res;
     memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         ag_res.num = volume;
         BTA_AgResult(btif_hf_cb[idx].handle,
@@ -1062,7 +1205,7 @@
         return BT_STATUS_FAIL;
     }
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         tBTA_AG_RES_DATA    ag_res;
 
@@ -1100,7 +1243,7 @@
         return BT_STATUS_FAIL;
     }
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         tBTA_AG_RES_DATA    ag_res;
 
@@ -1127,33 +1270,6 @@
 
 /*******************************************************************************
 **
-** Function         bind_response
-**
-** Description      Send +BIND response
-**
-** Returns          bt_status_t
-**
-*******************************************************************************/
-static bt_status_t bind_response(bthf_hf_ind_type_t ind_id, bthf_hf_ind_status_t ind_status,
-                                 bt_bdaddr_t * bd_addr)
-{
-    CHECK_BTHF_INIT();
-
-    int index = btif_hf_idx_by_bdaddr(bd_addr);
-    if (!is_connected(bd_addr) || index == BTIF_HF_INVALID_IDX)
-        return BT_STATUS_FAIL;
-
-    tBTA_AG_RES_DATA ag_res;
-    memset(&ag_res, 0, sizeof(ag_res));
-    ag_res.ind.id = ind_id;
-    ag_res.ind.on_demand = (ind_status == BTHF_HF_IND_ENABLED);
-
-    BTA_AgResult(btif_hf_cb[index].handle, BTA_AG_BIND_RES, &ag_res);
-    return BT_STATUS_SUCCESS;
-}
-
-/*******************************************************************************
-**
 ** Function         formatted_at_response
 **
 ** Description      Pre-formatted AT response, typically in response to unknown AT cmd
@@ -1173,7 +1289,7 @@
         return BT_STATUS_FAIL;
     }
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         /* Format the response and send */
         memset (&ag_res, 0, sizeof (ag_res));
@@ -1208,10 +1324,15 @@
         return BT_STATUS_FAIL;
     }
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         send_at_result((response_code == BTHF_AT_RESPONSE_OK) ? BTA_AG_OK_DONE
                         : BTA_AG_OK_ERROR, error_code, idx);
+        if (response_code == BTHF_AT_RESPONSE_OK && send_bvra_other_index)
+        {
+            send_bvra_update(idx);
+            send_bvra_other_index = FALSE;
+        }
         return BT_STATUS_SUCCESS;
     }
 
@@ -1244,7 +1365,7 @@
         return BT_STATUS_FAIL;
     }
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         tBTA_AG_RES_DATA    ag_res;
         int                 xx;
@@ -1306,6 +1427,8 @@
     BOOLEAN activeCallUpdated = FALSE;
     int idx, i;
 
+    memset(&ag_res, 0, sizeof(ag_res));
+
     /* hf_idx is index of connected HS that sent ATA/BLDN,
             otherwise index of latest connected HS */
     if (hf_idx != BTIF_HF_INVALID_IDX)
@@ -1313,13 +1436,13 @@
     else
         idx = btif_hf_latest_connected_idx();
 
-    BTIF_TRACE_DEBUG("phone_state_change: idx = %d", idx);
+    BTIF_TRACE_IMP("phone_state_change: idx = %d", idx);
 
     /* Check if SLC is connected */
     if (btif_hf_check_if_slc_connected() != BT_STATUS_SUCCESS)
         return BT_STATUS_NOT_READY;
 
-    BTIF_TRACE_DEBUG("phone_state_change: num_active=%d [prev: %d]  num_held=%d[prev: %d]"
+    BTIF_TRACE_IMP("phone_state_change: num_active=%d [prev: %d]  num_held=%d[prev: %d]"
                       " call_setup=%s [prev: %s]", num_active, btif_hf_cb[idx].num_active,
                        num_held, btif_hf_cb[idx].num_held, dump_hf_call_state(call_setup_state),
                        dump_hf_call_state(btif_hf_cb[idx].call_setup_state));
@@ -1361,11 +1484,14 @@
     if ( ((num_active + num_held) > 0) && (btif_hf_cb[idx].num_active == 0) && (btif_hf_cb[idx].num_held == 0) &&
          (btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE) )
     {
-        BTIF_TRACE_DEBUG("%s: Active/Held call notification received without call setup update",
+        BTIF_TRACE_IMP("%s: Active/Held call notification received without call setup update",
                           __FUNCTION__);
 
         memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
         ag_res.audio_handle = btif_hf_cb[idx].handle;
+
+        BTIF_TRACE_IMP("%s: Moving the audio_state to CONNECTING", __FUNCTION__);
+        btif_hf_cb[idx].audio_state = BTHF_AUDIO_STATE_CONNECTING;
         /* Addition call setup with the Active call
         ** CIND response should have been updated.
         ** just open SCO conenction.
@@ -1381,7 +1507,7 @@
     /* Ringing call changed? */
     if (call_setup_state != btif_hf_cb[idx].call_setup_state)
     {
-        BTIF_TRACE_DEBUG("%s: Call setup states changed. old: %s new: %s",
+        BTIF_TRACE_IMP("%s: Call setup states changed. old: %s new: %s",
             __FUNCTION__, dump_hf_call_state(btif_hf_cb[idx].call_setup_state),
             dump_hf_call_state(call_setup_state));
         memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
@@ -1397,6 +1523,10 @@
                         {
                             res = BTA_AG_IN_CALL_CONN_RES;
                             ag_res.audio_handle = btif_hf_cb[idx].handle;
+
+                            BTIF_TRACE_IMP("%s: Moving the audio_state to CONNECTING",
+                                              __FUNCTION__);
+                            btif_hf_cb[idx].audio_state = BTHF_AUDIO_STATE_CONNECTING;
                         }
                         else if (num_held > btif_hf_cb[idx].num_held)
                             res = BTA_AG_IN_CALL_HELD_RES;
@@ -1447,14 +1577,33 @@
                 break;
             case BTHF_CALL_STATE_DIALING:
                 if (!(num_active + num_held))
+                {
                     ag_res.audio_handle = btif_hf_cb[idx].handle;
+
+                    BTIF_TRACE_IMP("%s: Moving the audio_state to CONNECTING", __FUNCTION__);
+                    btif_hf_cb[idx].audio_state = BTHF_AUDIO_STATE_CONNECTING;
+                }
+                else
+                {
+                    BTIF_TRACE_DEBUG("%s: Already in a call, don't set audio handle", __FUNCTION__);
+                }
                 res = BTA_AG_OUT_CALL_ORIG_RES;
                 break;
             case BTHF_CALL_STATE_ALERTING:
                 /* if we went from idle->alert, force SCO setup here. dialing usually triggers it */
                 if ((btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE) &&
                         !(num_active + num_held))
+                {
                     ag_res.audio_handle = btif_hf_cb[idx].handle;
+
+                    BTIF_TRACE_IMP("%s: Moving the audio_state to CONNECTING", __FUNCTION__);
+                    btif_hf_cb[idx].audio_state = BTHF_AUDIO_STATE_CONNECTING;
+                }
+                else
+                {
+                    BTIF_TRACE_DEBUG("%s: Already in a call or prev call state was dialing,"
+                                                           " don't set audio handle", __FUNCTION__);
+                }
                 res = BTA_AG_OUT_CALL_ALERT_RES;
                 break;
             default:
@@ -1462,7 +1611,7 @@
                 status = BT_STATUS_PARM_INVALID;
                 break;
         }
-        BTIF_TRACE_DEBUG("%s: Call setup state changed. res=%d, audio_handle=%d", __FUNCTION__, res, ag_res.audio_handle);
+        BTIF_TRACE_IMP("%s: Call setup state changed. res=%d, audio_handle=%d", __FUNCTION__, res, ag_res.audio_handle);
 
         if (res)
             BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
@@ -1486,7 +1635,7 @@
     if (!activeCallUpdated && ((num_active + num_held) !=
                  (btif_hf_cb[idx].num_active + btif_hf_cb[idx].num_held)) )
     {
-        BTIF_TRACE_DEBUG("%s: Active call states changed. old: %d new: %d", __FUNCTION__, btif_hf_cb[idx].num_active, num_active);
+        BTIF_TRACE_IMP("%s: Active call states changed. old: %d new: %d", __FUNCTION__, btif_hf_cb[idx].num_active, num_active);
         send_indicator_update(BTA_AG_IND_CALL, ((num_active + num_held) > 0) ? 1 : 0);
     }
 
@@ -1494,7 +1643,7 @@
     if (num_held != btif_hf_cb[idx].num_held  ||
         ((num_active == 0) && ((num_held + btif_hf_cb[idx].num_held) > 1)))
     {
-        BTIF_TRACE_DEBUG("%s: Held call states changed. old: %d new: %d",
+        BTIF_TRACE_IMP("%s: Held call states changed. old: %d new: %d",
                         __FUNCTION__, btif_hf_cb[idx].num_held, num_held);
         send_indicator_update(BTA_AG_IND_CALLHELD, ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1)));
     }
@@ -1505,39 +1654,57 @@
          (num_active == btif_hf_cb[idx].num_active) &&
          (num_held == btif_hf_cb[idx].num_held) )
     {
-        BTIF_TRACE_DEBUG("%s: Calls swapped", __FUNCTION__);
+        BTIF_TRACE_IMP("%s: Calls swapped", __FUNCTION__);
         send_indicator_update(BTA_AG_IND_CALLHELD, 1);
     }
 
 update_call_states:
     for (i = 0; i < btif_max_hf_clients; i++)
     {
-        btif_hf_cb[i].num_active = num_active;
-        btif_hf_cb[i].num_held = num_held;
-        btif_hf_cb[i].call_setup_state = call_setup_state;
+        if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED) {
+            btif_hf_cb[i].num_active = num_active;
+            btif_hf_cb[i].num_held = num_held;
+            btif_hf_cb[i].call_setup_state = call_setup_state;
+        }
     }
     return status;
 }
 
 /*******************************************************************************
 **
-** Function         btif_hf_is_call_idle
+** Function         btif_hf_is_call_vr_idle
 **
 ** Description      returns true if no call is in progress
 **
 ** Returns          bt_status_t
 **
 *******************************************************************************/
-BOOLEAN btif_hf_is_call_idle()
+BOOLEAN btif_hf_is_call_vr_idle()
 {
-    if (bt_hf_callbacks == NULL)
-        return TRUE;
+    int i, j = 1;
 
-    for (int i = 0; i < btif_max_hf_clients; ++i)
+    if (bt_hf_callbacks == NULL)
     {
-        if ((btif_hf_cb[i].call_setup_state != BTHF_CALL_STATE_IDLE)
-            || ((btif_hf_cb[i].num_held + btif_hf_cb[i].num_active) > 0))
-            return FALSE;
+        return TRUE;
+    }
+    for (i = 0; i < btif_max_hf_clients; i++)
+    {
+        BTIF_TRACE_EVENT("%s: call_setup_state: %d for handle: %d",
+              __FUNCTION__, btif_hf_cb[i].call_setup_state, btif_hf_cb[i].handle);
+        BTIF_TRACE_EVENT("num_held: %d, num_active: %d for handle: %d",
+                btif_hf_cb[i].num_held, btif_hf_cb[i].num_active, btif_hf_cb[i].handle);
+        j &= ((btif_hf_cb[i].call_setup_state == BTHF_CALL_STATE_IDLE) &&
+                ((btif_hf_cb[i].num_held + btif_hf_cb[i].num_active) == 0));
+    }
+
+    if (j && (btif_hf_check_if_sco_connected() != BT_STATUS_SUCCESS))
+    {
+        BTIF_TRACE_EVENT("%s: call state idle and no sco connected.", __FUNCTION__);
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
     }
 
     return TRUE;
@@ -1580,13 +1747,13 @@
 *******************************************************************************/
 static void  cleanup( void )
 {
-    BTIF_TRACE_EVENT("%s", __FUNCTION__);
+    BTIF_TRACE_IMP("%s", __FUNCTION__);
 
-    if (bt_hf_callbacks)
-    {
-        btif_disable_service(BTA_HFP_SERVICE_ID);
-        bt_hf_callbacks = NULL;
-    }
+#if (defined(BTIF_HF_SERVICES) && (BTIF_HF_SERVICES & BTA_HFP_SERVICE_MASK))
+    btif_disable_service(BTA_HFP_SERVICE_ID);
+#else
+    btif_disable_service(BTA_HSP_SERVICE_ID);
+#endif
 }
 
 /*******************************************************************************
@@ -1623,6 +1790,151 @@
     return BT_STATUS_SUCCESS;
 }
 
+/*******************************************************************************
+**
+** Function         bind_response
+**
+** Description      response for BIND READ command
+**                  Can be iteratively called for each Hf indicator.
+**
+** Returns          bt_status_t
+**
+*******************************************************************************/
+static bt_status_t bind_response(int anum, bthf_hf_indicator_status_t status,
+                               bt_bdaddr_t *bd_addr)
+{
+    CHECK_BTHF_INIT();
+
+    int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+    if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
+    {
+        BTIF_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
+        return BT_STATUS_FAIL;
+    }
+
+    if (idx != BTIF_HF_INVALID_IDX)
+    {
+        tBTA_AG_RES_DATA    ag_res;
+        int                 xx;
+
+        memset (&ag_res, 0, sizeof (ag_res));
+
+        /* Format the response */
+        BTIF_TRACE_EVENT("bind_response: anum : [%d] status %d ", anum, status);
+        xx = snprintf (ag_res.str, sizeof(ag_res.str), "%d,%d", anum, status);
+
+        BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BIND_RES, &ag_res);
+
+        return BT_STATUS_SUCCESS;
+    }
+
+    return BT_STATUS_FAIL;
+}
+
+/*******************************************************************************
+**
+** Function         bind_string_response
+**
+** Description      response for BIND TEST command
+**
+** Returns          bt_status_t
+**
+*******************************************************************************/
+static bt_status_t bind_string_response(const char* res,
+                               bt_bdaddr_t *bd_addr)
+{
+    CHECK_BTHF_INIT();
+
+    int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+    if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
+    {
+        BTIF_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
+        return BT_STATUS_FAIL;
+    }
+
+    if (idx != BTIF_HF_INVALID_IDX)
+    {
+        tBTA_AG_RES_DATA    ag_res;
+        int                 xx;
+
+        memset (&ag_res, 0, sizeof (ag_res));
+
+        /* Format the response */
+        xx = snprintf (ag_res.str, sizeof(ag_res.str), "%s", res);
+
+        BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BIND_RES, &ag_res);
+
+        return BT_STATUS_SUCCESS;
+    }
+
+    return BT_STATUS_FAIL;
+}
+
+static void set_voip_network_type_wifi_hci_cmd_complete(tBTM_VSC_CMPL* p_data)
+{
+    UINT8         *stream,  status, subcmd;
+    UINT16        opcode, length;
+
+    if (p_data && (stream = (UINT8*)p_data->p_param_buf))
+    {
+        opcode = p_data->opcode;
+        length = p_data->param_len;
+        STREAM_TO_UINT8(status, stream);
+        STREAM_TO_UINT8(subcmd, stream);
+        BTIF_TRACE_DEBUG("%s opcode = 0x%04X, length = %d, status = %d, subcmd = %d",
+                __FUNCTION__, opcode, length, status, subcmd);
+        if (status == HCI_SUCCESS)
+        {
+            BTIF_TRACE_DEBUG("btm_SetVoipNetworkTypeWifi status success");
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         voip_network_type_wifi
+**
+** Description      BT app updates the connectivity network used for VOIP as Wifi
+**
+** Returns          bt_status_t
+**
+*******************************************************************************/
+static bt_status_t voip_network_type_wifi(bthf_voip_state_t isVoipStarted,
+                                          bthf_voip_call_network_type_t isNetworkWifi)
+{
+    UINT8           cmd[3], *p_cursor;
+    UINT8           sub_cmd = HCI_VSC_SUBCODE_VOIP_NETWORK_WIFI;
+    tBTM_STATUS     status = BTM_NO_RESOURCES;
+    int             idx = btif_hf_latest_connected_idx();
+
+    CHECK_BTHF_INIT();
+
+    if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
+    {
+        BTIF_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
+        return BT_STATUS_FAIL;
+    }
+
+    p_cursor = cmd;
+    memset(cmd, 0, 3);
+
+    *p_cursor++ = sub_cmd;
+    *p_cursor++ = isVoipStarted;
+    *p_cursor++ = isNetworkWifi;
+
+    if ((status = BTM_VendorSpecificCommand(HCI_VSC_VOIP_NETWORK_WIFI_OCF, sizeof(cmd),
+            cmd, set_voip_network_type_wifi_hci_cmd_complete)) != BTM_CMD_STARTED)
+    {
+        BTIF_TRACE_ERROR("%s: status %d", __FUNCTION__, status);
+        return BT_STATUS_FAIL;
+    }
+
+    return BT_STATUS_SUCCESS;
+
+}
+
 static const bthf_interface_t bthfInterface = {
     sizeof(bthfInterface),
     init,
@@ -1643,6 +1955,8 @@
     cleanup,
     configure_wbs,
     bind_response,
+    bind_string_response,
+    voip_network_type_wifi,
 };
 
 /*******************************************************************************
@@ -1656,28 +1970,60 @@
 *******************************************************************************/
 bt_status_t btif_hf_execute_service(BOOLEAN b_enable)
 {
-     char * p_service_names[] = BTIF_HF_SERVICE_NAMES;
-     int i;
-     if (b_enable)
-     {
-          /* Enable and register with BTA-AG */
-          BTA_AgEnable (BTA_AG_PARSE, bte_hf_evt);
-              for (i = 0; i < btif_max_hf_clients; i++)
-              {
-                  BTA_AgRegister(BTIF_HF_SERVICES, BTIF_HF_SECURITY,
-                      BTIF_HF_FEATURES, p_service_names, bthf_hf_id[i]);
-              }
-     }
-     else {
-         /* De-register AG */
-         for (i = 0; i < btif_max_hf_clients; i++)
-         {
-             BTA_AgDeregister(btif_hf_cb[i].handle);
-         }
-         /* Disable AG */
-         BTA_AgDisable();
-     }
-     return BT_STATUS_SUCCESS;
+    char * p_service_names[] = BTIF_HF_SERVICE_NAMES;
+    int i;
+    uint8_t no_of_codecs = 0;
+    uint8_t* codecs;
+    char value[PROPERTY_VALUE_MAX];
+
+    BTIF_TRACE_IMP("%s: enable: %d", __FUNCTION__, b_enable);
+
+    if (b_enable)
+    {
+        /* Enable and register with BTA-AG */
+        BTA_AgEnable (BTA_AG_PARSE, bte_hf_evt);
+        codecs = controller_get_interface()->get_local_supported_codecs(&no_of_codecs);
+        if (codecs != NULL)
+        {
+            for (i = 0; i < no_of_codecs; i++)
+            {
+                if (codecs[i] == BTA_AG_MSBC_CODEC)
+                {
+                    btif_features |= BTA_AG_FEAT_CODEC;
+                    break;
+                }
+            }
+        }
+        else
+        {
+            /* Read the property if local supported codecs commands is not supported */
+            if (property_get("ro.bluetooth.hfp.ver", value, "1.5") &&
+                     (!strcmp(value, "1.6") || !strcmp(value, "1.7")) )
+               btif_features |= BTA_AG_FEAT_CODEC;
+        }
+
+        for (i = 0; i < btif_max_hf_clients; i++)
+        {
+            BTA_AgRegister(BTIF_HF_SERVICES, BTIF_HF_SECURITY,
+                btif_features, p_service_names, bthf_hf_id[i]);
+        }
+    }
+    else {
+        if (bt_hf_callbacks)
+        {
+            BTIF_TRACE_IMP("%s: setting call backs to NULL", __FUNCTION__);
+            bt_hf_callbacks = NULL;
+        }
+        /* De-register AG */
+        for (i = 0; i < btif_max_hf_clients; i++)
+        {
+            BTA_AgDeregister(btif_hf_cb[i].handle);
+        }
+        /* Disable AG */
+        BTA_AgDisable();
+    }
+    BTIF_TRACE_IMP("%s: enable: %d completed", __FUNCTION__, b_enable);
+    return BT_STATUS_SUCCESS;
 }
 
 /*******************************************************************************
diff --git a/btif/src/btif_hf_client.c b/btif/src/btif_hf_client.c
index bdf0874..5ebb965 100644
--- a/btif/src/btif_hf_client.c
+++ b/btif/src/btif_hf_client.c
@@ -400,7 +400,7 @@
 {
     CHECK_BTHF_CLIENT_SLC_CONNECTED();
 
-    if (number)
+    if (strcmp(number,"") != 0)
     {
         BTA_HfClientSendAT(btif_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_ATD, 0, 0, number);
     }
@@ -640,11 +640,7 @@
 {
     BTIF_TRACE_EVENT("%s", __FUNCTION__);
 
-    if (bt_hf_client_callbacks)
-    {
-        btif_disable_service(BTA_HFP_HS_SERVICE_ID);
-        bt_hf_client_callbacks = NULL;
-    }
+    btif_disable_service(BTA_HFP_HS_SERVICE_ID);
 }
 
 /*******************************************************************************
@@ -738,7 +734,7 @@
     tBTA_HF_CLIENT *p_data = (tBTA_HF_CLIENT *)p_param;
     bdstr_t bdstr;
 
-    BTIF_TRACE_DEBUG("%s: event=%s (%u)", __FUNCTION__, dump_hf_client_event(event), event);
+    BTIF_TRACE_IMP("%s: event=%s (%u)", __FUNCTION__, dump_hf_client_event(event), event);
 
     switch (event)
     {
@@ -899,6 +895,12 @@
         case BTA_HF_CLIENT_RING_INDICATION:
             HAL_CBACK(bt_hf_client_callbacks, ring_indication_cb);
             break;
+        case BTA_HF_CLIENT_CGMI_EVT:
+            HAL_CBACK(bt_hf_client_callbacks, cgmi_cb, p_data->cgmi.name);
+            break;
+        case BTA_HF_CLIENT_CGMM_EVT:
+            HAL_CBACK(bt_hf_client_callbacks, cgmm_cb, p_data->cgmm.model);
+            break;
         default:
             BTIF_TRACE_WARNING("%s: Unhandled event: %d", __FUNCTION__, event);
             break;
@@ -945,7 +947,7 @@
      {
           /* Enable and register with BTA-HFClient */
           BTA_HfClientEnable(bte_hf_client_evt);
-          if (strcmp(btif_hf_client_version, "1.6") == 0)
+          if (strtof(btif_hf_client_version, NULL) >= 1.6)
           {
               BTIF_TRACE_EVENT("Support Codec Nego. %d ", BTIF_HF_CLIENT_FEATURES);
               BTA_HfClientRegister(BTIF_HF_CLIENT_SECURITY, BTIF_HF_CLIENT_FEATURES,
@@ -964,9 +966,15 @@
      }
      else
      {
+         if (bt_hf_client_callbacks)
+         {
+             BTIF_TRACE_IMP("%s: setting call backs to NULL", __FUNCTION__);
+             bt_hf_client_callbacks = NULL;
+         }
          BTA_HfClientDeregister(btif_hf_client_cb.handle);
          BTA_HfClientDisable();
      }
+     BTIF_TRACE_IMP("%s: enable: %d completed", __FUNCTION__, b_enable);
      return BT_STATUS_SUCCESS;
 }
 
diff --git a/btif/src/btif_hh.c b/btif/src/btif_hh.c
index 9d883bb..a4057cc 100644
--- a/btif/src/btif_hh.c
+++ b/btif/src/btif_hh.c
@@ -150,6 +150,7 @@
 extern void btif_dm_cb_remove_bond(bt_bdaddr_t *bd_addr);
 extern BOOLEAN check_cod_hid(const bt_bdaddr_t *remote_bdaddr);
 extern int  scru_ascii_2_hex(char *p_ascii, int len, UINT8 *p_hex);
+extern void btif_dm_hh_open_success(bt_bdaddr_t *bdaddr);
 extern void btif_dm_hh_open_failed(bt_bdaddr_t *bdaddr);
 
 /*****************************************************************************
@@ -482,6 +483,13 @@
     LOG_INFO(LOG_TAG, "%s: bda = %02x:%02x:%02x:%02x:%02x:%02x", __FUNCTION__,
          bd_addr.address[0], bd_addr.address[1], bd_addr.address[2], bd_addr.address[3], bd_addr.address[4], bd_addr.address[5]);
 
+    /* Check if this is not received while hid host service is disabled */
+    if (btif_hh_cb.status == BTIF_HH_DISABLED)
+    {
+        BTIF_TRACE_WARNING("%s: HH service not enabled", __FUNCTION__);
+        return;
+    }
+
     for (i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {
         p_added_dev = &btif_hh_cb.added_devices[i];
         if (memcmp(&(p_added_dev->bd_addr),&bd_addr, 6) == 0) {
@@ -556,6 +564,12 @@
     BTIF_TRACE_DEBUG("%s", __FUNCTION__);
     btif_hh_device_t *p_dev;
     char bd_str[18];
+    /* Check if this is not received while hid host service is disabled */
+    if (btif_hh_cb.status == BTIF_HH_DISABLED)
+    {
+        BTIF_TRACE_WARNING("%s: HH service not enabled", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
     sprintf(bd_str, "%02X:%02X:%02X:%02X:%02X:%02X",
             bd_addr->address[0],  bd_addr->address[1],  bd_addr->address[2],  bd_addr->address[3],
             bd_addr->address[4], bd_addr->address[5]);
@@ -595,6 +609,12 @@
     int i;
     BD_ADDR *bda = (BD_ADDR*)bd_addr;
     CHECK_BTHH_INIT();
+    /* Check if this is not received while hid host service is disabled */
+    if (btif_hh_cb.status == BTIF_HH_DISABLED)
+    {
+        BTIF_TRACE_WARNING("%s: HH service not enabled", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
     dev = btif_hh_find_dev_by_bda(bd_addr);
     BTIF_TRACE_DEBUG("Connect _hh");
     sprintf(bda_str, "%02X:%02X:%02X:%02X:%02X:%02X",
@@ -677,6 +697,22 @@
     BTA_HhSetReport(p_dev->dev_handle, r_type, p_buf);
 }
 
+/*******************************************************************************
+**
+** Function         btif_hh_getreport
+**
+** Description      getreport initiated from the BTIF thread context
+**
+** Returns          void
+**
+*******************************************************************************/
+void btif_hh_getreport(btif_hh_device_t *p_dev, bthh_report_type_t r_type,
+                        UINT8 reportId, UINT16 bufferSize)
+
+{
+    BTA_HhGetReport(p_dev->dev_handle, r_type, reportId, bufferSize);
+}
+
 /*****************************************************************************
 **   Section name (Group of functions)
 *****************************************************************************/
@@ -758,6 +794,7 @@
                     BTA_HhClose(p_data->conn.handle);
                 }
                 else {
+                    btif_dm_hh_open_success((bt_bdaddr_t*)p_data->conn.bda);
                     BTIF_TRACE_WARNING("BTA_HH_OPEN_EVT: Found device...Getting dscp info for handle ... %d",p_data->conn.handle);
                     memcpy(&(p_dev->bd_addr), p_data->conn.bda, BD_ADDR_LEN);
                     btif_hh_cb.status = BTIF_HH_DEV_CONNECTED;
@@ -857,7 +894,7 @@
             break;
 
         case BTA_HH_GET_PROTO_EVT:
-            p_dev = btif_hh_find_connected_dev_by_handle(p_data->dev_status.handle);
+            p_dev = btif_hh_find_connected_dev_by_handle(p_data->hs_data.handle);
             BTIF_TRACE_WARNING("BTA_HH_GET_PROTO_EVT: status = %d, handle = %d, proto = [%d], %s",
                  p_data->hs_data.status, p_data->hs_data.handle,
                  p_data->hs_data.rsp_data.proto_mode,
@@ -890,6 +927,9 @@
             BTIF_TRACE_DEBUG("BTA_HH_GET_IDLE_EVT: handle = %d, status = %d, rate = %d",
                  p_data->hs_data.handle, p_data->hs_data.status,
                  p_data->hs_data.rsp_data.idle_rate);
+            p_dev = btif_hh_find_connected_dev_by_handle(p_data->hs_data.handle);
+            HAL_CBACK(bt_hh_callbacks, idle_time_cb,(bt_bdaddr_t*) &(p_dev->bd_addr),
+                (bthh_status_t) p_data->hs_data.status, p_data->hs_data.rsp_data.idle_rate);
             break;
 
         case BTA_HH_SET_IDLE_EVT:
@@ -935,6 +975,7 @@
                     bdcpy(bda, p_dev->bd_addr.address);
                     tBTA_HH_DEV_DSCP_INFO dscp_info;
                     bt_status_t ret;
+                    memset(&dscp_info, 0, sizeof(dscp_info));
                     bdcpy(bda, p_dev->bd_addr.address);
                     btif_hh_copy_hid_info(&dscp_info, &p_data->dscp_info);
                     BTIF_TRACE_DEBUG("BTA_HH_GET_DSCP_EVT:bda = %02x:%02x:%02x:%02x:%02x:%02x",
@@ -1207,6 +1248,11 @@
 *******************************************************************************/
 static bt_status_t connect( bt_bdaddr_t *bd_addr)
 {
+    if (btif_hh_cb.status == BTIF_HH_DISABLED)
+    {
+        BTIF_TRACE_WARNING("%s: HH service not enabled", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
     if(btif_hh_cb.status != BTIF_HH_DEV_CONNECTING)
     {
         btif_transfer_context(btif_hh_handle_evt, BTIF_HH_CONNECT_REQ_EVT,
@@ -1311,6 +1357,8 @@
         return BT_STATUS_FAIL;
     }
 
+    memset(&dscp_info, 0, sizeof(dscp_info));
+
     dscp_info.vendor_id  = hid_info.vendor_id;
     dscp_info.product_id = hid_info.product_id;
     dscp_info.version    = hid_info.version;
@@ -1333,6 +1381,74 @@
 
 /*******************************************************************************
 **
+** Function         get_idle_time
+**
+** Description      Get the HID idle time
+**
+** Returns         bt_status_t
+**
+*******************************************************************************/
+static bt_status_t get_idle_time(bt_bdaddr_t *bd_addr)
+{
+    CHECK_BTHH_INIT();
+    btif_hh_device_t *p_dev;
+    BD_ADDR* bda = (BD_ADDR*) bd_addr;
+
+    BTIF_TRACE_DEBUG(" addr = %02X:%02X:%02X:%02X:%02X:%02X",
+         (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
+
+    if (btif_hh_cb.status == BTIF_HH_DISABLED) {
+        BTIF_TRACE_ERROR("%s: Error, HH status = %d", __FUNCTION__, btif_hh_cb.status);
+        return BT_STATUS_FAIL;
+    }
+
+    p_dev = btif_hh_find_connected_dev_by_bda(bd_addr);
+    if (p_dev != NULL) {
+        BTA_HhGetIdle(p_dev->dev_handle);
+    }
+    else {
+        return BT_STATUS_FAIL;
+    }
+    return BT_STATUS_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function         set_idle_time
+**
+** Description      Set the HID idle time
+**
+** Returns         bt_status_t
+**
+*******************************************************************************/
+static bt_status_t set_idle_time (bt_bdaddr_t *bd_addr, uint8_t idle_time)
+{
+    CHECK_BTHH_INIT();
+    btif_hh_device_t *p_dev;
+    BD_ADDR* bda = (BD_ADDR*) bd_addr;
+
+    BTIF_TRACE_DEBUG("addr = %02X:%02X:%02X:%02X:%02X:%02X",
+         (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
+
+    if (btif_hh_cb.status == BTIF_HH_DISABLED) {
+        BTIF_TRACE_ERROR("%s: Error, HH status = %d", __FUNCTION__, btif_hh_cb.status);
+        return BT_STATUS_FAIL;
+    }
+
+    p_dev = btif_hh_find_connected_dev_by_bda(bd_addr);
+    if (p_dev == NULL) {
+        BTIF_TRACE_WARNING(" Error, device %02X:%02X:%02X:%02X:%02X:%02X not opened.",
+             (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
+        return BT_STATUS_FAIL;
+    }
+    else {
+        BTA_HhSetIdle(p_dev->dev_handle, idle_time);
+    }
+    return BT_STATUS_SUCCESS;
+}
+
+/*******************************************************************************
+**
 ** Function         get_protocol
 **
 ** Description      Get the HID proto mode.
@@ -1624,8 +1740,8 @@
     set_info,
     get_protocol,
     set_protocol,
-//    get_idle_time,
-//    set_idle_time,
+    get_idle_time,
+    set_idle_time,
     get_report,
     set_report,
     send_data,
diff --git a/btif/src/btif_hl.c b/btif/src/btif_hl.c
index 97ca1c2..dcd8db4 100644
--- a/btif/src/btif_hl.c
+++ b/btif/src/btif_hl.c
@@ -3190,6 +3190,7 @@
 
             break;
         case BTIF_HL_REG_APP:
+            reg_counter++;
             p_acb  = BTIF_HL_GET_APP_CB_PTR(p_data->reg.app_idx);
             BTIF_TRACE_DEBUG("Rcv BTIF_HL_REG_APP app_idx=%d reg_pending=%d", p_data->reg.app_idx, p_acb->reg_pending);
             if (btif_hl_get_state() == BTIF_HL_STATE_ENABLED && p_acb->reg_pending)
@@ -3211,6 +3212,7 @@
             break;
 
         case BTIF_HL_UNREG_APP:
+            reg_counter--;
             BTIF_TRACE_DEBUG("Rcv BTIF_HL_UNREG_APP app_idx=%d", p_data->unreg.app_idx );
             p_acb = BTIF_HL_GET_APP_CB_PTR(p_data->unreg.app_idx);
             if (btif_hl_get_state() == BTIF_HL_STATE_ENABLED)
@@ -4038,7 +4040,6 @@
     if (btif_hl_find_app_idx(((UINT8)app_id), &app_idx))
     {
         evt_param.unreg.app_idx = app_idx;
-        reg_counter --;
         len = sizeof(btif_hl_unreg_t);
         status = btif_transfer_context (btif_hl_proc_cb_evt, BTIF_HL_UNREG_APP,
                                         (char*) &evt_param, len, NULL);
@@ -4164,7 +4165,6 @@
         evt_param.reg.app_idx = app_idx;
         len = sizeof(btif_hl_reg_t);
         p_acb->reg_pending = TRUE;
-        reg_counter++;
         BTIF_TRACE_DEBUG("calling btif_transfer_context status=%d app_id=%d", status, *app_id);
         status = btif_transfer_context (btif_hl_proc_cb_evt, BTIF_HL_REG_APP,
                                         (char*) &evt_param, len, NULL);
diff --git a/btif/src/btif_l2cap.c b/btif/src/btif_l2cap.c
new file mode 100644
index 0000000..c44fe57
--- /dev/null
+++ b/btif/src/btif_l2cap.c
@@ -0,0 +1,514 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *        * Redistributions of source code must retain the above copyright
+ *          notice, this list of conditions and the following disclaimer.
+ *        * Redistributions in binary form must reproduce the above copyright
+ *            notice, this list of conditions and the following disclaimer in the
+ *            documentation and/or other materials provided with the distribution.
+ *        * Neither the name of The Linux Foundation nor
+ *            the names of its contributors may be used to endorse or promote
+ *            products derived from this software without specific prior written
+ *            permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.    IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <hardware/bluetooth.h>
+
+#define LOG_NDDEBUG 0
+#define LOG_TAG "bluedroid"
+
+#include "btif_api.h"
+#include "bt_utils.h"
+#include "l2cdefs.h"
+#include "l2c_api.h"
+#include <l2c_int.h>
+#if TEST_APP_INTERFACE == TRUE
+#include <bt_testapp.h>
+
+static tL2CAP_APPL_INFO    *pl2test_l2c_appl = NULL;
+static bt_status_t L2cap_Init (tL2CAP_APPL_INFO *p);
+static bt_status_t L2cap_Register (UINT16 psm, BOOLEAN ConnType, UINT16 SecLevel);
+static bt_status_t L2cap_DeRegister (UINT16 psm);
+static UINT16 L2cap_AllocatePSM(void);
+static UINT16 L2cap_Connect(UINT16 psm, bt_bdaddr_t *bd_addr);
+static BOOLEAN L2cap_ConnectRsp(BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid,
+                                        UINT16 result, UINT16 status);
+static UINT16 L2cap_ErtmConnect(UINT16 psm, BD_ADDR p_bd_addr, tL2CAP_ERTM_INFO *p_ertm_info);
+static BOOLEAN  L2cap_ErtmConnectRsp (BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid,
+                                              UINT16 result, UINT16 status,
+                                              tL2CAP_ERTM_INFO *p_ertm_info);
+static BOOLEAN L2cap_ConfigReq(UINT16 cid, tL2CAP_CFG_INFO *p_cfg);
+static BOOLEAN L2cap_ConfigRsp(UINT16 cid, tL2CAP_CFG_INFO *p_cfg);
+static BOOLEAN L2cap_DisconnectReq (UINT16 cid);
+static BOOLEAN L2cap_DisconnectRsp (UINT16 cid);
+static UINT8 L2cap_DataWrite (UINT16 cid, char *p_data, UINT32 len);
+static BOOLEAN L2cap_Ping (BD_ADDR p_bd_addr, tL2CA_ECHO_RSP_CB *p_cb);
+static BOOLEAN  L2cap_Echo (BD_ADDR p_bd_addr, BT_HDR *p_data, tL2CA_ECHO_DATA_CB *p_callback);
+static BOOLEAN L2cap_SetIdleTimeout (UINT16 cid, UINT16 timeout, BOOLEAN is_global);
+static BOOLEAN L2cap_SetIdleTimeoutByBdAddr(BD_ADDR bd_addr, UINT16 timeout);
+static void L2cap_SetSecConnOnlyMode (BOOLEAN secvalue);
+static UINT8 L2cap_SetDesireRole (UINT8 new_role);
+static UINT16 L2cap_LocalLoopbackReq (UINT16 psm, UINT16 handle, BD_ADDR p_bd_addr);
+static UINT16   L2cap_FlushChannel (UINT16 lcid, UINT16 num_to_flush);
+static BOOLEAN L2cap_SetAclPriority (BD_ADDR bd_addr, UINT8 priority);
+static BOOLEAN L2cap_FlowControl (UINT16 cid, BOOLEAN data_enabled);
+static BOOLEAN L2cap_SendTestSFrame (UINT16 cid, BOOLEAN rr_or_rej, UINT8 back_track);
+static BOOLEAN L2cap_SetTxPriority (UINT16 cid, tL2CAP_CHNL_PRIORITY priority);
+static BOOLEAN L2cap_RegForNoCPEvt(tL2CA_NOCP_CB *p_cb, BD_ADDR p_bda);
+static BOOLEAN L2cap_SetChnlDataRate (UINT16 cid, tL2CAP_CHNL_DATA_RATE tx, tL2CAP_CHNL_DATA_RATE rx);
+static BOOLEAN L2cap_SetFlushTimeout (BD_ADDR bd_addr, UINT16 flush_tout);
+static UINT8 L2cap_DataWriteEx (UINT16 cid, BT_HDR *p_data, UINT16 flags);
+static BOOLEAN L2cap_SetChnlFlushability (UINT16 cid, BOOLEAN is_flushable);
+static BOOLEAN L2cap_GetPeerFeatures (BD_ADDR bd_addr, UINT32 *p_ext_feat, UINT8 *p_chnl_mask);
+static BOOLEAN L2cap_GetBDAddrbyHandle (UINT16 handle, BD_ADDR bd_addr);
+static UINT8 L2cap_GetChnlFcrMode (UINT16 lcid);
+static UINT16 L2cap_SendFixedChnlData (UINT16 fixed_cid, BD_ADDR rem_bda, BT_HDR *p_buf);
+static bt_status_t L2cap_LE_Register (UINT16 le_psm, BOOLEAN ConnType, UINT16 SecLevel, UINT8 enc_key_size);
+static bt_status_t L2cap_LE_DeRegister (UINT16 psm);
+static UINT16 L2cap_LE_Connect(UINT16 le_psm , BD_ADDR address, tL2CAP_LE_CFG_INFO *p_cfg);
+static BOOLEAN L2cap_LE_ConnectRsp (BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid, UINT16 result,
+                             UINT16 status, tL2CAP_LE_CFG_INFO *p_cfg);
+//static BOOLEAN L2cap_LE_ConnectRsp (BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid, tL2CAP_LE_CFG_INFO *p_cfg);
+static BOOLEAN L2cap_LE_FlowControl (UINT16 lcid, UINT16 credits);
+static void L2cap_LE_freebuf(BT_HDR *p_buf);
+
+static const btl2cap_interface_t btl2capInterface = {
+    sizeof(btl2cap_interface_t),
+    L2cap_Init,
+    L2cap_Register,
+    L2cap_DeRegister,
+    L2cap_AllocatePSM,
+    L2cap_Connect,
+    L2cap_ConnectRsp,
+    L2cap_ErtmConnect,
+    L2cap_ErtmConnectRsp,
+    L2cap_ConfigReq,
+    L2cap_ConfigRsp,
+    L2cap_DisconnectReq,
+    L2cap_DisconnectRsp,
+    L2cap_DataWrite,
+    L2cap_Ping,
+    L2cap_Echo,
+    L2cap_SetIdleTimeout,
+    L2cap_SetIdleTimeoutByBdAddr,
+    L2cap_SetDesireRole,
+    L2cap_SetSecConnOnlyMode,
+    L2cap_LocalLoopbackReq,
+    L2cap_FlushChannel,
+    L2cap_SetAclPriority,
+    L2cap_FlowControl,
+    L2cap_SendTestSFrame,
+    L2cap_SetTxPriority,
+    L2cap_RegForNoCPEvt,
+    L2cap_SetChnlDataRate,
+    L2cap_SetFlushTimeout,
+    L2cap_DataWriteEx,
+    L2cap_SetChnlFlushability,
+    L2cap_GetPeerFeatures,
+    L2cap_GetBDAddrbyHandle,
+    L2cap_GetChnlFcrMode,
+    L2cap_SendFixedChnlData,
+    NULL, // cleanup,
+    L2cap_LE_Register,
+    L2cap_LE_DeRegister,
+    L2cap_LE_Connect,
+    L2cap_LE_ConnectRsp,
+    L2cap_LE_FlowControl,
+    L2cap_LE_freebuf,
+};
+
+const btl2cap_interface_t *btif_l2cap_get_interface(void)
+{
+    BTIF_TRACE_EVENT("%s", __FUNCTION__);
+    return &btl2capInterface;
+}
+
+
+/*
+- Take PSM only once during the Register func call.
+- Rest of the functions (connect, dereg) uses the same PSM. This way user need not pass it again.
+  This will also avoid additional error checks like unregistered psm is passed etc.
+ */
+
+static UINT16 g_Psm = 0;
+static UINT16 g_lcid = 0;
+
+static bt_status_t L2cap_Init (tL2CAP_APPL_INFO *p)
+{
+    pl2test_l2c_appl = p;
+    return BT_STATUS_SUCCESS;
+}
+/*******************************************************************************
+**
+** Function         L2cap_Register
+**
+** Description      This function is called during the task startup
+**                  to register interface functions with L2CAP.
+**
+*******************************************************************************/
+static bt_status_t L2cap_Register (UINT16 psm, BOOLEAN ConnType, UINT16 SecLevel)
+{
+
+    BTIF_TRACE_DEBUG("L2cap_Register :: psm=%d", psm);
+    if (!BTM_SetSecurityLevel (ConnType, "l2test", /*BTM_SEC_SERVICE_SDP_SERVER*/ BTM_SEC_PROTO_L2CAP,
+                               SecLevel, psm, 0, 0))
+    {
+        BTIF_TRACE_DEBUG("Error:: BTM_SetSecurityLevel failed");
+        return BT_STATUS_FAIL;
+}
+#if 1
+    if(4113 == psm) {
+        if (!BTM_SetSecurityLevel (ConnType, "l2test 4113", /*BTM_SEC_SERVICE_SDP_SERVER*/ BTM_SEC_PROTO_L2CAP,
+                                   SecLevel, psm, 0, 0)) {
+            BTIF_TRACE_DEBUG("Error:: BTM_SetSecurityLevel failed");
+            return BT_STATUS_FAIL;
+        }
+    }
+#endif
+    g_Psm = L2CA_Register (psm, pl2test_l2c_appl);
+    if(0 == g_Psm) {
+        BTIF_TRACE_DEBUG("Error:: L2CA_Register failed");
+        return BT_STATUS_FAIL;
+    }
+   return BT_STATUS_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function L2cap_LE_Register
+**
+** Description This function is called during the task startup
+** to register interface functions with L2CAP.
+**
+*******************************************************************************/
+static bt_status_t L2cap_LE_Register (UINT16 le_psm, BOOLEAN ConnType, UINT16 SecLevel,
+                                          UINT8 enc_key_size)
+{
+
+    BTIF_TRACE_DEBUG("LE-L2CAP: %s le_psm=%d, SecLevel=%d ", __FUNCTION__, le_psm, SecLevel);
+#if 0
+    if (!BTM_SetSecurityLevel (ConnType, "l2c_le_test", BTM_SEC_SERVICE_ATT,
+            SecLevel, le_psm))
+    {
+        BTIF_TRACE_ERROR("LE-L2CAP: BTM_SetSecurityLevel failed");
+        return BT_STATUS_FAIL;
+    }
+    if (!BTM_SetBleEncKeySize ("l2c_le_test", enc_key_size, le_psm))
+    {
+        BTIF_TRACE_ERROR("LE-L2CAP: BTM_SetBleEncKeySize failed");
+        return BT_STATUS_FAIL;
+    }
+#endif
+
+    g_Psm = L2CA_REGISTER_COC (le_psm, pl2test_l2c_appl,
+                                       AMP_AUTOSWITCH_ALLOWED|AMP_USE_AMP_IF_POSSIBLE);
+
+    if(0 == g_Psm) {
+        BTIF_TRACE_ERROR("LE-L2CAP: L2cap_LE_Register failed");
+        return BT_STATUS_FAIL;
+    }
+
+    if (!BTM_SetSecurityLevel (ConnType, "l2c_le_test", BTM_SEC_SERVICE_ATT,
+            SecLevel, le_psm, 0, 0))
+    {
+        BTIF_TRACE_ERROR("LE-L2CAP: BTM_SetSecurityLevel failed");
+        return BT_STATUS_FAIL;
+    }
+    return BT_STATUS_SUCCESS;
+}
+
+static UINT16 L2cap_LE_Connect (UINT16 le_psm , BD_ADDR address, tL2CAP_LE_CFG_INFO *p_cfg)
+{
+    BTIF_TRACE_DEBUG("LE-L2CAP: %s:: %0x %0x %0x %0x %0x %0x", __FUNCTION__,
+    address[0], address[1], address[2],address[3],address[4],address[5]);
+
+    if (0 == (g_lcid = L2CA_CONNECT_COC_REQ (le_psm, address, p_cfg))) {
+        BTIF_TRACE_ERROR("LE-L2CAP: L2CA_LE_CreditBasedConn_Req failed for le_psm ");
+    }
+    return g_lcid;
+}
+
+static BOOLEAN L2cap_LE_ConnectRsp (BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid, UINT16 result,
+                             UINT16 status, tL2CAP_LE_CFG_INFO *p_cfg)
+{
+     p_cfg->credits = L2CAP_LE_DEFAULT_CREDIT;
+     p_cfg->mtu = L2CAP_LE_DEFAULT_MTU;
+     p_cfg->mps = L2CAP_LE_DEFAULT_MPS;
+
+    L2CA_CONNECT_COC_RSP (p_bd_addr, id, lcid, L2CAP_CONN_OK, L2CAP_CONN_OK, p_cfg);
+#if 0
+    if (!L2CA_LE_CreditBasedConn_Rsp (p_bd_addr, id, lcid, conn_info)) {
+        BTIF_TRACE_ERROR("LE-L2CAP: L2CA_LE_CreditBasedConn_Rsp failed");
+        return BT_STATUS_FAIL;
+    }
+#endif
+    return BT_STATUS_SUCCESS;
+}
+
+static BOOLEAN L2cap_LE_FlowControl (UINT16 lcid, UINT16 credits)
+{
+    if (!L2CA_LE_SetFlowControlCredits (lcid, credits)) {
+        BTIF_TRACE_ERROR("LE-L2CAP: L2CA_LE_SetFlowControlCredits failed");
+        return BT_STATUS_FAIL;
+    }
+    return BT_STATUS_SUCCESS;
+}
+static void L2cap_LE_freebuf (BT_HDR *p_buf)
+{
+     osi_free(p_buf);
+}
+
+static bt_status_t L2cap_LE_DeRegister (UINT16 psm)
+{
+    L2CA_DeregisterLECoc(psm);
+    return BT_STATUS_SUCCESS;
+}
+
+static bt_status_t L2cap_DeRegister (UINT16 psm)
+{
+    L2CA_Deregister(psm);
+    return BT_STATUS_SUCCESS;
+}
+
+static UINT16 L2cap_AllocatePSM(void)
+{
+    BTIF_TRACE_DEBUG("L2cap_AllocatePSM");
+    return L2CA_AllocatePSM();
+}
+
+static UINT16 L2cap_Connect(UINT16 psm, bt_bdaddr_t *bd_addr)
+{
+
+    BTIF_TRACE_DEBUG("L2cap_Connect:: %0x %0x %0x %0x %0x %0x", bd_addr->address[0],bd_addr->address[1],
+                         bd_addr->address[2],bd_addr->address[3],bd_addr->address[4],bd_addr->address[5]);
+
+    if (0 == (g_lcid = L2CA_ConnectReq (psm, bd_addr->address)))
+    {
+        BTIF_TRACE_DEBUG("Error:: L2CA_ConnectReq failed for psm %d", psm);
+    }
+    return g_lcid;
+}
+
+static BOOLEAN L2cap_ConnectRsp(BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid,
+                                        UINT16 result, UINT16 status)
+{
+    if (!L2CA_ConnectRsp (p_bd_addr, id, lcid, result, status)) {
+        BTIF_TRACE_DEBUG("L2CA_ConnectRsp:: error ");
+        return  BT_STATUS_FAIL;
+    }
+    return BT_STATUS_SUCCESS;
+}
+
+static UINT16 L2cap_ErtmConnect(UINT16 psm, BD_ADDR address, tL2CAP_ERTM_INFO *p_ertm_info)
+{
+    BTIF_TRACE_DEBUG("L2cap_ErtmConnect:: %0x %0x %0x %0x %0x %0x", address[0],address[1],address[2],address[3],address[4],address[5]);
+    if (0 == (g_lcid = L2CA_ErtmConnectReq (psm, address, p_ertm_info))) {
+        BTIF_TRACE_DEBUG("Error:: L2CA_ErtmConnectReq failed for psm %d", psm);
+    }
+    return g_lcid;
+}
+
+static BOOLEAN  L2cap_ErtmConnectRsp (BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid,
+                                             UINT16 result, UINT16 status,
+                                             tL2CAP_ERTM_INFO *p_ertm_info)
+{
+    if (!L2CA_ErtmConnectRsp (p_bd_addr, id, lcid, result, status, p_ertm_info)) {
+        BTIF_TRACE_DEBUG("L2CA_ErtmConnectRsp:: error ");
+        return BT_STATUS_FAIL;
+    }
+    return BT_STATUS_SUCCESS;
+}
+
+static BOOLEAN L2cap_ConfigReq(UINT16 cid, tL2CAP_CFG_INFO *p_cfg)
+{
+    BTIF_TRACE_DEBUG("L2cap_ConfigReq:: Invoked\n");
+    if (p_cfg->fcr_present)
+    {
+        BTIF_TRACE_DEBUG("L2cap_ConfigReq::  mode %u, txwinsz %u, max_trans %u, rtrans_tout %u, mon_tout %u, mps %u\n",
+                           p_cfg->fcr.mode, p_cfg->fcr.tx_win_sz, p_cfg->fcr.max_transmit,
+                           p_cfg->fcr.rtrans_tout,p_cfg->fcr.mon_tout, p_cfg->fcr.mps);
+    }
+    return L2CA_ConfigReq (cid, p_cfg);
+}
+
+static BOOLEAN L2cap_ConfigRsp(UINT16 cid, tL2CAP_CFG_INFO *p_cfg)
+{
+    BTIF_TRACE_DEBUG("L2cap_ConfigRsp:: Invoked");
+    return L2CA_ConfigRsp (cid, p_cfg);
+}
+
+static BOOLEAN L2cap_DisconnectReq (UINT16 cid)
+{
+    BTIF_TRACE_DEBUG("L2cap_DisconnectReq:: cid=%d", cid);
+    return L2CA_DisconnectReq(cid);
+}
+static BOOLEAN L2cap_DisconnectRsp (UINT16 cid)
+{
+    BTIF_TRACE_DEBUG("L2cap_DisconnectRsp:: Invoked");
+    return L2CA_DisconnectRsp (cid);
+}
+
+static UINT8 L2cap_DataWrite (UINT16 cid, char *p_data, UINT32 len)
+{
+    BTIF_TRACE_DEBUG("L2cap_DataWrite:: Invoked");
+    BT_HDR  *p_msg = NULL;
+    UINT8   *ptr, *p_start;
+
+    p_msg = (BT_HDR *) osi_malloc(BT_DEFAULT_BUFFER_SIZE);
+    BTIF_TRACE_DEBUG("osi_malloc");
+    if (!p_msg)
+    {
+        BTIF_TRACE_DEBUG("No resource to allocate");
+        return BT_STATUS_FAIL;
+    }
+    p_msg->offset = L2CAP_MIN_OFFSET;
+    ptr = p_start = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
+    p_msg->len = len;    //Sends len bytes, irrespective of what you copy to the buffer
+    memcpy(ptr, p_data, len);
+    return L2CA_DataWrite(cid, p_msg);
+}
+
+
+static BOOLEAN L2cap_Ping (BD_ADDR p_bd_addr, tL2CA_ECHO_RSP_CB *p_cb)
+{
+    BTIF_TRACE_DEBUG("L2cap_Ping:: Invoked");
+    return L2CA_Ping (p_bd_addr, p_cb);
+}
+
+static BOOLEAN  L2cap_Echo (BD_ADDR p_bd_addr, BT_HDR *p_data, tL2CA_ECHO_DATA_CB *p_callback)
+{
+    BTIF_TRACE_DEBUG("L2cap_Echo:: Invoked");
+    return L2CA_Echo (p_bd_addr, p_data, p_callback);
+}
+
+static BOOLEAN L2cap_SetIdleTimeout (UINT16 cid, UINT16 timeout, BOOLEAN is_global)
+{
+    BTIF_TRACE_DEBUG("L2cap_SetIdleTimeout:: Invoked");
+    return L2CA_SetIdleTimeout (cid, timeout, is_global);
+}
+
+
+static BOOLEAN L2cap_SetIdleTimeoutByBdAddr(BD_ADDR bd_addr, UINT16 timeout)
+{
+    BTIF_TRACE_DEBUG("L2cap_SetIdleTimeoutByBdAddr:: Invoked");
+    return L2CA_SetIdleTimeoutByBdAddr(bd_addr, timeout,BT_TRANSPORT_BR_EDR);
+}
+
+static void L2cap_SetSecConnOnlyMode(BOOLEAN secvalue)
+{
+    BTIF_TRACE_DEBUG("L2cap_SetSecConnOnlyMode:: Invoked");
+    BTM_SetSecureConnectionsOnly(secvalue);
+}
+
+static UINT8 L2cap_SetDesireRole (UINT8 new_role)
+{
+    BTIF_TRACE_DEBUG("L2CA_SetDesireRole:: Invoked");
+    return L2CA_SetDesireRole (new_role);
+}
+
+
+static UINT16 L2cap_LocalLoopbackReq (UINT16 psm, UINT16 handle, BD_ADDR p_bd_addr)
+{
+    BTIF_TRACE_DEBUG("L2cap_LocalLoopbackReq:: Invoked");
+    return L2CA_LocalLoopbackReq (psm, handle, p_bd_addr);
+}
+
+static UINT16   L2cap_FlushChannel (UINT16 lcid, UINT16 num_to_flush)
+{
+    BTIF_TRACE_DEBUG("L2cap_FlushChannel:: Invoked");
+    return L2CA_FlushChannel (lcid, num_to_flush);
+}
+
+static BOOLEAN L2cap_SetAclPriority (BD_ADDR bd_addr, UINT8 priority)
+{
+    BTIF_TRACE_DEBUG("L2cap_SetAclPriority:: Invoked");
+    return L2CA_SetAclPriority (bd_addr, priority);
+}
+
+static BOOLEAN L2cap_FlowControl (UINT16 cid, BOOLEAN data_enabled)
+{
+    BTIF_TRACE_DEBUG("L2cap_FlowControl:: Invoked with LocalBusy=%s\n", (data_enabled)? "FALSE" :"TRUE");
+    return L2CA_FlowControl (cid, data_enabled);
+}
+
+static BOOLEAN L2cap_SendTestSFrame (UINT16 cid, BOOLEAN rr_or_rej, UINT8 back_track)
+{
+    BTIF_TRACE_DEBUG("L2cap_SendTestSFrame:: Invoked");
+    return L2CA_SendTestSFrame (cid, rr_or_rej, back_track);
+}
+
+static BOOLEAN L2cap_SetTxPriority (UINT16 cid, tL2CAP_CHNL_PRIORITY priority)
+{
+    BTIF_TRACE_DEBUG("L2cap_SetTxPriority:: Invoked");
+    return L2CA_SetTxPriority (cid, priority);
+}
+
+static BOOLEAN L2cap_RegForNoCPEvt(tL2CA_NOCP_CB *p_cb, BD_ADDR p_bda)
+{
+    BTIF_TRACE_DEBUG("L2cap_RegForNoCPEvt:: Invoked");
+    return L2CA_RegForNoCPEvt(p_cb, p_bda);
+}
+
+static BOOLEAN L2cap_SetChnlDataRate (UINT16 cid, tL2CAP_CHNL_DATA_RATE tx, tL2CAP_CHNL_DATA_RATE rx)
+{
+    BTIF_TRACE_DEBUG("L2cap_SetChnlDataRate:: Invoked");
+    return L2CA_SetChnlDataRate (cid, tx, rx);
+}
+
+static BOOLEAN L2cap_SetFlushTimeout (BD_ADDR bd_addr, UINT16 flush_tout)
+{
+    BTIF_TRACE_DEBUG("L2cap_SetFlushTimeout:: Invoked");
+    return L2CA_SetFlushTimeout (bd_addr, flush_tout);
+}
+
+static UINT8 L2cap_DataWriteEx (UINT16 cid, BT_HDR *p_data, UINT16 flags)
+{
+    BTIF_TRACE_DEBUG("L2cap_DataWriteEx:: Invoked");
+    return L2CA_DataWriteEx (cid, p_data, flags);
+}
+static BOOLEAN L2cap_SetChnlFlushability (UINT16 cid, BOOLEAN is_flushable)
+{
+    BTIF_TRACE_DEBUG("L2cap_SetChnlFlushability:: Invoked");
+    return L2CA_SetChnlFlushability (cid, is_flushable);
+}
+static BOOLEAN L2cap_GetPeerFeatures (BD_ADDR bd_addr, UINT32 *p_ext_feat, UINT8 *p_chnl_mask)
+{
+    BTIF_TRACE_DEBUG("L2cap_GetPeerFeatures:: Invoked");
+    return L2CA_GetPeerFeatures (bd_addr, p_ext_feat, p_chnl_mask);
+}
+static BOOLEAN L2cap_GetBDAddrbyHandle (UINT16 handle, BD_ADDR bd_addr)
+{
+    BTIF_TRACE_DEBUG("L2cap_GetBDAddrbyHandle:: Invoked");
+    return L2CA_GetBDAddrbyHandle (handle, bd_addr);
+}
+static UINT8 L2cap_GetChnlFcrMode (UINT16 lcid)
+{
+    BTIF_TRACE_DEBUG("L2cap_GetChnlFcrMode:: Invoked");
+    return L2CA_GetChnlFcrMode (lcid);
+}
+
+//---------------------FIXED CHANNEL API ---------------------
+static UINT16 L2cap_SendFixedChnlData (UINT16 fixed_cid, BD_ADDR rem_bda, BT_HDR *p_buf)
+{
+    BTIF_TRACE_DEBUG("L2cap_SendFixedChnlData:: Invoked");
+    p_buf->event = 20;
+    return L2CA_SendFixedChnlData(fixed_cid, rem_bda, p_buf);
+}
+#endif //TEST_APP_INTERFACE
diff --git a/btif/src/btif_mcap.c b/btif/src/btif_mcap.c
new file mode 100644
index 0000000..f0b84b3
--- /dev/null
+++ b/btif/src/btif_mcap.c
@@ -0,0 +1,220 @@
+/*
+ *Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the followin conditions are met:
+ *        * Redistributions of source code must retain the above copyright
+ *          notice, this list of conditions and the followin disclaimer.
+ *        * Redistributions in binary form must reproduce the above copyriht
+ *            notice, this list of conditions and the followin disclaimer in the
+ *            documentation and/or other materials provided with the distribution.
+ *        * Neither the name of The Linux Foundation nor
+ *            the names of its contributors may be used to endorse or promote
+ *            products derived from this software without specific prior written
+ *            permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.    IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <hardware/bluetooth.h>
+
+
+#define LOG_NDDEBUG 0
+#define LOG_TAG "bluedroid"
+
+#include "btif_api.h"
+#include "bt_utils.h"
+#include "bt_testapp.h"
+#include "btm_api.h"
+#include "btu.h"
+#include "btm_api.h"
+#include "mca_api.h"
+
+#ifdef TEST_APP_INTERFACE
+
+static void McaInit(void)
+{
+    MCA_Init();
+}
+
+static tMCA_HANDLE McaRegister(tMCA_REG *p_reg, tMCA_CTRL_CBACK *p_cback)
+{
+    tMCA_HANDLE Ret = 0;
+    BTM_SetConnectability (1, 0, 0);
+    Ret = MCA_Register(p_reg, p_cback);
+    ALOGI("McaRegister");
+    return Ret;
+}
+
+static void Mca_Deregister(tMCA_HANDLE handle)
+{
+    MCA_Deregister(handle);
+    ALOGI("McaRegister");
+}
+
+static tMCA_RESULT Mca_CreateDep(tMCA_HANDLE handle, tMCA_DEP *p_dep, tMCA_CS *p_cs)
+{
+    tMCA_RESULT	Ret = 0;
+    ALOGI("Mca_CreateDep Enter");
+    Ret = MCA_CreateDep(handle, p_dep, p_cs);
+    ALOGI("Mca_CreateDep Exit");
+    return Ret;
+}
+
+static tMCA_RESULT Mca_DeleteDep(tMCA_HANDLE handle, tMCA_DEP dep)
+{
+    tMCA_RESULT  Ret = 0;
+    Ret = MCA_DeleteDep(handle, dep);
+    ALOGI("MCA_DeleteDep Exit");
+    return Ret;
+}
+
+
+static tMCA_RESULT Mca_ConnectReq(tMCA_HANDLE handle, BD_ADDR bd_addr, UINT16 ctrl_psm, UINT16 sec_mask)
+{
+    tMCA_RESULT Ret = 0;
+    Ret = MCA_ConnectReq(handle, bd_addr, ctrl_psm, sec_mask);
+    ALOGI("MCA_ConnectReq");
+    return Ret;
+}
+
+static tMCA_RESULT Mca_DisconnectReq(tMCA_CL mcl)
+{
+    tMCA_RESULT Ret = 0;
+    Ret = MCA_DisconnectReq(mcl);
+    ALOGI("Mca_DisconnectReq");
+    return Ret;
+}
+
+
+static tMCA_RESULT Mca_CreateMdl(tMCA_CL mcl, tMCA_DEP dep, UINT16 data_psm,
+                                         UINT16 mdl_id, UINT8 peer_dep_id,
+                                         UINT8 cfg, const tMCA_CHNL_CFG *p_chnl_cfg)
+{
+    tMCA_RESULT Ret = 0;
+    Ret = MCA_CreateMdl(mcl, dep, data_psm, mdl_id, peer_dep_id, cfg, p_chnl_cfg);
+    ALOGI("MCA_CreateMdl");
+    return Ret;
+}
+
+
+static tMCA_RESULT Mca_CreateMdlRsp(tMCA_CL mcl, tMCA_DEP dep, UINT16 mdl_id, UINT8 cfg, UINT8 rsp_code, const tMCA_CHNL_CFG *p_chnl_cfg)
+{
+    tMCA_RESULT Ret = 0;
+    Ret = MCA_CreateMdlRsp(mcl, dep, mdl_id, cfg, rsp_code, p_chnl_cfg);
+    ALOGI("Mca_CreateMdlRsp");
+    return Ret;
+}
+
+
+static tMCA_RESULT Mca_CloseReq(tMCA_DL mdl)
+{
+    tMCA_RESULT Ret = 0;
+    Ret = MCA_CloseReq(mdl);
+    ALOGI("Mca_CloseReq");
+    return Ret;
+}
+
+static tMCA_RESULT Mca_ReconnectMdl(tMCA_CL mcl, tMCA_DEP dep, UINT16 data_psm, UINT16 mdl_id, const tMCA_CHNL_CFG *p_chnl_cfg)
+{
+    tMCA_RESULT Ret = 0;
+    Ret = MCA_ReconnectMdl(mcl, dep, data_psm, mdl_id, p_chnl_cfg);
+    ALOGI("Mca_ReconnectMdl");
+    return Ret;
+}
+
+static tMCA_RESULT Mca_ReconnectMdlRsp(tMCA_CL mcl, tMCA_DEP dep, UINT16 mdl_id, UINT8 rsp_code, const tMCA_CHNL_CFG *p_chnl_cfg)
+{
+    tMCA_RESULT Ret = 0;
+    Ret = MCA_ReconnectMdlRsp(mcl, dep, mdl_id, rsp_code, p_chnl_cfg);
+    ALOGI("Mca_ReconnectMdl");
+    return Ret;
+}
+
+static tMCA_RESULT Mca_DataChnlCfg(tMCA_CL mcl, const tMCA_CHNL_CFG *p_chnl_cfg)
+{
+    tMCA_RESULT Ret = 0;
+    Ret = MCA_DataChnlCfg(mcl, p_chnl_cfg);
+    ALOGI("Mca_DataChnlCfg");
+    return Ret;
+}
+
+static tMCA_RESULT Mca_Abort(tMCA_CL mcl)
+{
+    tMCA_RESULT Ret = 0;
+    Ret = MCA_Abort(mcl);
+    ALOGI("MCA_Abort");
+    return Ret;
+}
+
+
+static tMCA_RESULT Mca_Delete(tMCA_CL mcl, UINT16 mdl_id)
+{
+    tMCA_RESULT Ret = 0;
+    Ret = MCA_Delete(mcl, mdl_id);
+    ALOGI("Mca_Delete");
+    return Ret;
+}
+
+static tMCA_RESULT Mca_WriteReq(tMCA_DL mdl, BT_HDR *p_pkt)
+{
+    tMCA_RESULT Ret = 0;
+    Ret = MCA_WriteReq(mdl, p_pkt);
+    ALOGI("Mca_Delete");
+    return Ret;
+}
+
+static UINT16 Mca_GetL2CapChannel (tMCA_DL mdl)
+{
+    UINT16 Ret = 0;
+    Ret = MCA_GetL2CapChannel(mdl);
+    ALOGI("Mca_GetL2CapChannel");
+    return Ret;
+}
+
+static const btmcap_interface_t btmcaInterface = {
+    sizeof(btmcap_interface_t),
+    McaInit,
+    McaRegister,
+    Mca_Deregister,
+    Mca_CreateDep,
+    Mca_DeleteDep,
+    Mca_ConnectReq,
+    Mca_DisconnectReq,
+    Mca_CreateMdl,
+    Mca_CreateMdlRsp,
+    Mca_CloseReq,
+    Mca_ReconnectMdl,
+    Mca_ReconnectMdlRsp,
+    Mca_DataChnlCfg,
+    Mca_Abort,
+    Mca_Delete,
+    Mca_WriteReq,
+    Mca_GetL2CapChannel
+};
+
+
+const btmcap_interface_t *btif_mcap_get_interface(void)
+{
+    //BTIF_TRACE_EVENT1("%s", __FUNCTION__);
+    //printf("\n%s\n", __FUNCTION__);
+    return &btmcaInterface;
+}
+
+
+#endif
diff --git a/btif/src/btif_media_task.c b/btif/src/btif_media_task.c
index cf464e1..fb5a27b 100644
--- a/btif/src/btif_media_task.c
+++ b/btif/src/btif_media_task.c
@@ -1,4 +1,9 @@
 /******************************************************************************
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a contribution.
+ ******************************************************************************/
+/******************************************************************************
  *
  *  Copyright (C) 2009-2012 Broadcom Corporation
  *
@@ -25,6 +30,9 @@
  **                 audio & video processing
  **
  ******************************************************************************/
+#ifdef BT_AUDIO_SYSTRACE_LOG
+#define ATRACE_TAG ATRACE_TAG_ALWAYS
+#endif
 
 #define LOG_TAG "bt_btif_media"
 
@@ -34,23 +42,37 @@
 #include <pthread.h>
 #include <stdint.h>
 #include <stdio.h>
+#include <dlfcn.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <audio_utils/primitives.h>
+#include <audio_utils/format.h>
 
 #include <hardware/bluetooth.h>
 
+#include "osi/include/alarm.h"
+#include "osi/include/fixed_queue.h"
+#include "osi/include/log.h"
+#include "osi/include/metrics.h"
+#include "osi/include/mutex.h"
+#include "osi/include/thread.h"
+#include "bt_utils.h"
 #include "a2d_api.h"
 #include "a2d_int.h"
 #include "a2d_sbc.h"
+#include "a2d_aptx.h"
+#include "a2d_aptx_hd.h"
+#include "a2d_aac.h"
 #include "audio_a2dp_hw.h"
 #include "bt_target.h"
 #include "bta_api.h"
 #include "bta_av_api.h"
 #include "bta_av_ci.h"
 #include "bta_av_sbc.h"
+#include "bta_av_aac.h"
 #include "bta_sys.h"
 #include "bta_sys_int.h"
 #include "btif_av.h"
@@ -62,12 +84,6 @@
 #include "bt_common.h"
 #include "device/include/controller.h"
 #include "l2c_api.h"
-#include "osi/include/alarm.h"
-#include "osi/include/fixed_queue.h"
-#include "osi/include/log.h"
-#include "osi/include/metrics.h"
-#include "osi/include/mutex.h"
-#include "osi/include/thread.h"
 
 #if (BTA_AV_INCLUDED == TRUE)
 #include "sbc_encoder.h"
@@ -82,12 +98,23 @@
 #include "btif_avrcp_audio_track.h"
 #endif
 
+#include "bthost_ipc.h"
 #if (BTA_AV_SINK_INCLUDED == TRUE)
 OI_CODEC_SBC_DECODER_CONTEXT context;
 OI_UINT32 contextData[CODEC_DATA_WORDS(2, SBC_CODEC_FAST_FILTER_BUFFERS)];
 OI_INT16 pcmData[15*SBC_MAX_SAMPLES_PER_FRAME*SBC_MAX_CHANNELS];
 #endif
 
+#ifdef BT_AUDIO_SYSTRACE_LOG
+#include <cutils/trace.h>
+#define PERF_SYSTRACE 1
+#endif
+
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+#include "bta_api.h"
+#endif
+
+
 /*****************************************************************************
  **  Constants
  *****************************************************************************/
@@ -117,6 +144,21 @@
     BTIF_MEDIA_AUDIO_SINK_CFG_UPDATE,
     BTIF_MEDIA_AUDIO_SINK_CLEAR_TRACK,
     BTIF_MEDIA_AUDIO_SINK_SET_FOCUS_STATE
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+    ,BTIF_MEDIA_START_VS_CMD,
+    BTIF_MEDIA_STOP_VS_CMD,
+    BTIF_MEDIA_RESET_VS_STATE,
+    BTIF_MEDIA_VS_A2DP_START_SUCCESS,
+    BTIF_MEDIA_VS_A2DP_STOP_SUCCESS,
+    BTIF_MEDIA_VS_A2DP_MEDIA_CHNL_CFG_SUCCESS,
+    BTIF_MEDIA_VS_A2DP_WRITE_SBC_CFG_SUCCESS,
+    BTIF_MEDIA_VS_A2DP_PREF_BIT_RATE_SUCCESS,
+    BTIF_MEDIA_VS_A2DP_SET_SCMST_HDR_SUCCESS,
+    BTIF_MEDIA_VS_A2DP_STOP_FAILURE,
+    BTIF_MEDIA_VS_A2DP_START_FAILURE,
+    BTIF_MEDIA_VS_A2DP_SELECTED_CODEC_SUCCESS,
+    BTIF_MEDIA_VS_A2DP_TRANSPORT_CFG_SUCCESS
+#endif
 };
 
 enum {
@@ -124,7 +166,6 @@
     MEDIA_TASK_STATE_ON = 1,
     MEDIA_TASK_STATE_SHUTTING_DOWN = 2
 };
-
 /* Macro to multiply the media task tick */
 #ifndef BTIF_MEDIA_NUM_TICK
 #define BTIF_MEDIA_NUM_TICK      1
@@ -136,7 +177,7 @@
 #define BTIF_MEDIA_TIME_TICK                     (20 * BTIF_MEDIA_NUM_TICK)
 #define A2DP_DATA_READ_POLL_MS    (BTIF_MEDIA_TIME_TICK / 2)
 #define BTIF_SINK_MEDIA_TIME_TICK_MS             (20 * BTIF_MEDIA_NUM_TICK)
-
+#define BTIF_REMOTE_START_TOUT 3000
 
 /* buffer pool */
 #define BTIF_MEDIA_AA_BUF_SIZE  BT_DEFAULT_BUFFER_SIZE
@@ -148,19 +189,39 @@
 #define BTIF_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE)
 #endif
 
+#if (BTA_AV_CO_CP_SCMS_T == TRUE)
+#define BTIF_MEDIA_AA_AAC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_AAC_HDR_SIZE + 1)
+#else
+#define BTIF_MEDIA_AA_AAC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_AAC_HDR_SIZE)
+#endif
+
+#if (BTA_AV_CO_CP_SCMS_T == TRUE)
+#define BTIF_MEDIA_AA_APTX_OFFSET (AVDT_MEDIA_OFFSET + 1)
+#define BTIF_MEDIA_AA_APTX_HD_OFFSET (AVDT_MEDIA_OFFSET + 1)
+#else
+#define BTIF_MEDIA_AA_APTX_OFFSET (AVDT_MEDIA_OFFSET - AVDT_MEDIA_HDR_SIZE) //no RTP header for aptX classic
+#define BTIF_MEDIA_AA_APTX_HD_OFFSET (AVDT_MEDIA_OFFSET) //there is an RTP header for aptX HD, but no CP byte
+#endif
 /* Define the bitrate step when trying to match bitpool value */
 #ifndef BTIF_MEDIA_BITRATE_STEP
 #define BTIF_MEDIA_BITRATE_STEP 5
 #endif
 
-#ifndef BTIF_A2DP_DEFAULT_BITRATE
-/* High quality quality setting @ 44.1 khz */
-#define BTIF_A2DP_DEFAULT_BITRATE 328
+#ifdef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
+#define BTIF_A2DP_DEFAULT_BITRATE 345
+
+#ifndef BTIF_A2DP_NON_EDR_MAX_RATE
+#define BTIF_A2DP_NON_EDR_MAX_RATE 237
 #endif
+#else
+#define BTIF_A2DP_DEFAULT_BITRATE 328
 
 #ifndef BTIF_A2DP_NON_EDR_MAX_RATE
 #define BTIF_A2DP_NON_EDR_MAX_RATE 229
 #endif
+#endif
+
+#define BTIF_A2DP_MAX_BITPOOL_MQ 35
 
 #if (BTA_AV_CO_CP_SCMS_T == TRUE)
 /* A2DP header will contain a CP header of size 1 */
@@ -206,6 +267,7 @@
 #define PACKET_PLAYED_PER_TICK_44 7
 #define PACKET_PLAYED_PER_TICK_32 5
 #define PACKET_PLAYED_PER_TICK_16 3
+#define MAX_MEDIA_WORKQUEUE_SEM_COUNT 1024
 
 /* Readability constants */
 #define SBC_FRAME_HEADER_SIZE_BYTES 4 // A2DP Spec v1.3, 12.4, Table 12.12
@@ -318,6 +380,11 @@
     tBTIF_AV_MEDIA_FEEDINGS media_feeding;
     tBTIF_AV_MEDIA_FEEDINGS_STATE media_feeding_state;
     SBC_ENC_PARAMS encoder;
+    UINT16 offset;
+    A2D_APTX_ENC_PARAMS aptxEncoderParams;
+    A2D_APTX_HD_ENC_PARAMS aptxhdEncoderParams;
+    UINT16 as16PcmBuffer[1024];
+    UINT32 as32PcmBuffer[1024];
     UINT8 busy_level;
     void* av_sm_hdl;
     UINT8 a2dp_cmd_pending; /* we can have max one command pending */
@@ -336,7 +403,18 @@
 #endif
     alarm_t *media_alarm;
     alarm_t *decode_alarm;
+    alarm_t *remote_start_alarm;
     btif_media_stats_t stats;
+//#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+    UINT8 max_bitpool;
+    UINT8 min_bitpool;
+    BOOLEAN vs_configs_exchanged;
+    BOOLEAN tx_started;
+    BOOLEAN tx_stop_initiated;
+    BOOLEAN tx_start_initiated;
+    BOOLEAN tx_enc_update_initiated;
+//#endif
+
     btif_media_stats_t accumulated_stats;
 #endif
 } tBTIF_MEDIA_CB;
@@ -382,6 +460,8 @@
 static void btif_media_task_handle_inc_media(tBT_SBC_HDR*p_msg);
 #endif
 
+BOOLEAN bta_av_co_audio_get_codec_config(UINT8 *p_config, UINT16 *p_minmtu, UINT8 type);
+
 #if (BTA_AV_INCLUDED == TRUE)
 static void btif_media_send_aa_frame(uint64_t timestamp_us);
 static void btif_media_task_feeding_state_reset(void);
@@ -402,14 +482,62 @@
 
 static void btif_media_task_aa_handle_timer(UNUSED_ATTR void *context);
 static void btif_media_task_avk_handle_timer(UNUSED_ATTR void *context);
-extern BOOLEAN btif_hf_is_call_idle();
+extern BOOLEAN btif_hf_is_call_vr_idle();
+extern int btif_get_latest_playing_device_idx();
+extern tBTA_AV_HNDL btif_av_get_playing_device_hdl();
+extern int btif_get_num_playing_devices();
+extern UINT16 btif_av_get_num_playing_devices(void);
+extern BOOLEAN btif_av_get_multicast_state();
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+extern tBTA_AV_HNDL btif_av_get_av_hdl_from_idx(UINT8 idx);
+extern BOOLEAN btif_av_is_under_handoff();
+extern BOOLEAN btif_av_is_device_disconnecting();
+extern void btif_av_reset_reconfig_flag();
+void btif_media_send_reset_vendor_state();
+void btif_media_on_start_vendor_command();
+void btif_media_on_stop_vendor_command();
+BOOLEAN btif_media_send_vendor_pref_bit_rate();
+BOOLEAN btif_media_send_vendor_write_sbc_cfg();
+BOOLEAN btif_media_send_vendor_media_chn_cfg();
+BOOLEAN btif_media_send_vendor_stop();
+void disconnect_a2dp_on_vendor_start_failure();
+BOOLEAN btif_media_send_vendor_selected_codec();
+BOOLEAN btif_media_send_vendor_transport_cfg();
+BOOLEAN btif_media_send_vendor_scmst_hdr();
+BOOLEAN btif_av_is_suspend_stop_pending_ack();
+#else
+#define btif_av_get_av_hdl_from_idx(idx) (0)
+#define btif_av_is_under_handoff() (0)
+#define btif_av_is_device_disconnecting() (0)
+#define btif_av_reset_reconfig_flag() (0)
+#define btif_media_send_reset_vendor_state() (0)
+#define btif_media_on_start_vendor_command() (0)
+#define btif_media_on_stop_vendor_command()  (0)
+#define btif_media_send_vendor_pref_bit_rate() (0)
+#define btif_media_send_vendor_write_sbc_cfg() (0)
+#define btif_media_send_vendor_media_chn_cfg() (0)
+#define btif_media_send_vendor_stop()        (0)
+#define disconnect_a2dp_on_vendor_start_failure() (0)
+#define btif_media_send_vendor_selected_codec() (0)
+#define btif_media_send_vendor_transport_cfg()  (0)
+#define btif_media_send_vendor_scmst_hdr()      (0)
+#define btif_av_is_suspend_stop_pending_ack() (0)
+#endif
+void btif_a2dp_remote_start_timer();
 
 static tBTIF_MEDIA_CB btif_media_cb;
 static int media_task_running = MEDIA_TASK_STATE_OFF;
+static BOOLEAN enc_update_in_progress = FALSE;
 
 static fixed_queue_t *btif_media_cmd_msg_queue;
 static thread_t *worker_thread;
 
+BOOLEAN bta_av_co_audio_get_codec_config(UINT8 *p_config, UINT16 *p_minmtu, UINT8 type);
+
+extern BOOLEAN bt_split_a2dp_enabled;
+extern int btif_max_av_clients;
+static uint8_t multicast_query = FALSE;
+extern BOOLEAN reconfig_a2dp;
 /*****************************************************************************
  **  Misc helper functions
  *****************************************************************************/
@@ -526,9 +654,22 @@
 
 static void log_tstamps_us(char *comment, uint64_t now_us)
 {
+    #define USEC_PER_MSEC 1000L
     static uint64_t prev_us = 0;
-    APPL_TRACE_DEBUG("[%s] ts %08llu, diff : %08llu, queue sz %d", comment, now_us, now_us - prev_us,
+    static uint64_t diff_us = 0;
+
+    diff_us = now_us - prev_us;
+    if ((diff_us / USEC_PER_MSEC) > (BTIF_MEDIA_TIME_TICK + 10))
+    {
+        APPL_TRACE_ERROR("[%s] ts %08llu, diff : %08llu, queue sz %d", comment, now_us, diff_us,
                 fixed_queue_length(btif_media_cb.TxAaQ));
+    }
+    else
+    {
+        APPL_TRACE_DEBUG("[%s] ts %08llu, diff : %08llu, queue sz %d", comment, now_us, diff_us,
+                fixed_queue_length(btif_media_cb.TxAaQ));
+    }
+
     prev_us = now_us;
 }
 
@@ -594,7 +735,11 @@
         CASE_RETURN_STR(A2DP_CTRL_CMD_STOP)
         CASE_RETURN_STR(A2DP_CTRL_CMD_SUSPEND)
         CASE_RETURN_STR(A2DP_CTRL_CMD_OFFLOAD_START)
-
+        CASE_RETURN_STR(A2DP_CTRL_CMD_OFFLOAD_SUPPORTED)
+        CASE_RETURN_STR(A2DP_CTRL_CMD_OFFLOAD_NOT_SUPPORTED)
+        CASE_RETURN_STR(A2DP_CTRL_GET_CODEC_CONFIG)
+        CASE_RETURN_STR(A2DP_CTRL_GET_MULTICAST_STATUS)
+        CASE_RETURN_STR(A2DP_CTRL_GET_CONNECTION_STATUS)
         default:
             return "UNKNOWN MSG ID";
     }
@@ -602,7 +747,7 @@
 
 static void btif_audiopath_detached(void)
 {
-    APPL_TRACE_EVENT("## AUDIO PATH DETACHED ##");
+    APPL_TRACE_IMP("## AUDIO PATH DETACHED ##");
 
     /*  send stop request only if we are actively streaming and haven't received
         a stop request. Potentially audioflinger detached abnormally */
@@ -616,7 +761,7 @@
 {
     UINT8 ack = status;
 
-    APPL_TRACE_EVENT("## a2dp ack : %s, status %d ##",
+    APPL_TRACE_IMP("## a2dp ack : %s, status %d ##",
           dump_a2dp_ctrl_event(btif_media_cb.a2dp_cmd_pending), status);
 
     /* sanity check */
@@ -643,7 +788,7 @@
     /* detach on ctrl channel means audioflinger process was terminated */
     if (n == 0)
     {
-        APPL_TRACE_EVENT("CTRL CH DETACHED");
+        APPL_TRACE_IMP("CTRL CH DETACHED");
         UIPC_Close(UIPC_CH_ID_AV_CTRL);
         /* we can operate only on datachannel, if af client wants to
            do send additional commands the ctrl channel would be reestablished */
@@ -651,7 +796,7 @@
         return;
     }
 
-    APPL_TRACE_DEBUG("a2dp-ctrl-cmd : %s", dump_a2dp_ctrl_event(cmd));
+    APPL_TRACE_IMP("a2dp-ctrl-cmd : %s", dump_a2dp_ctrl_event(cmd));
 
     btif_media_cb.a2dp_cmd_pending = cmd;
 
@@ -659,14 +804,31 @@
     {
         case A2DP_CTRL_CMD_CHECK_READY:
 
-            if (media_task_running == MEDIA_TASK_STATE_SHUTTING_DOWN)
+            if (!bt_split_a2dp_enabled && media_task_running == MEDIA_TASK_STATE_SHUTTING_DOWN)
             {
                 APPL_TRACE_WARNING("%s: A2DP command %s while media task shutting down",
                                    __func__, dump_a2dp_ctrl_event(cmd));
                 a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
                 return;
             }
-
+            if (bt_split_a2dp_enabled && !btif_hf_is_call_vr_idle())
+            {
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_INCALL_FAILURE);
+                return;
+            }
+            /*There can be instances where because of remote start received early, reconfig
+            flag may get reset, for such case check for tx_started flag set as well,
+            this would help returning proper status to MM*/
+            if (bt_split_a2dp_enabled)
+                APPL_TRACE_IMP("%s: A2DP command %s, reconfig: %d, tx_started: %d",
+                   __func__, dump_a2dp_ctrl_event(cmd), reconfig_a2dp,
+                   btif_media_cb.tx_started);
+            if (bt_split_a2dp_enabled && (btif_av_is_under_handoff() || reconfig_a2dp
+                || btif_media_cb.tx_started))
+            {
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+                return;
+            }
             /* check whether av is ready to setup a2dp datapath */
             if ((btif_av_stream_ready() == TRUE) || (btif_av_stream_started_ready() == TRUE))
             {
@@ -680,15 +842,27 @@
             }
             break;
 
+        case A2DP_CTRL_CMD_CHECK_STREAM_STARTED:
+
+            if((btif_av_stream_started_ready() == TRUE))
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+            else
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+            break;
+
         case A2DP_CTRL_CMD_START:
             /* Don't sent START request to stack while we are in call.
                Some headsets like the Sony MW600, don't allow AVDTP START
                in call and respond BAD_STATE. */
-            if (!btif_hf_is_call_idle())
+            if (!btif_hf_is_call_vr_idle())
             {
                 a2dp_cmd_acknowledge(A2DP_CTRL_ACK_INCALL_FAILURE);
                 break;
             }
+            APPL_TRACE_DEBUG("%s:A2DP command %s AV stream_started_ready %d",
+                             __func__, dump_a2dp_ctrl_event(cmd),btif_av_stream_started_ready());
+            APPL_TRACE_DEBUG("%s:A2DP command %s AV stream_ready %d",
+                             __func__, dump_a2dp_ctrl_event(cmd),btif_av_stream_ready());
 
             if (alarm_is_scheduled(btif_media_cb.media_alarm))
             {
@@ -698,11 +872,59 @@
                 break;
             }
 
-            if (btif_av_stream_ready() == TRUE)
+            if (alarm_is_scheduled(btif_media_cb.remote_start_alarm))
+            {
+                APPL_TRACE_WARNING("%s: remote a2dp started, cancle remote start timer",
+                                   __func__);
+                alarm_free(btif_media_cb.remote_start_alarm);
+                btif_media_cb.remote_start_alarm = NULL;
+                btif_dispatch_sm_event(BTIF_AV_RESET_REMOTE_STARTED_FLAG_UPDATE_AUDIO_STATE_EVT, NULL, 0);
+            }
+            /* In Dual A2dp, first check for started state of stream
+            * as we dont want to START again as while doing Handoff
+            * the stack state will be started, so it is not needed
+            * to send START again, just open the media socket
+            * and ACK the audio HAL.*/
+            if (btif_av_stream_started_ready())
+            {
+                if (!bt_split_a2dp_enabled)
+                {
+                    /* already started, setup audio data channel listener
+                    * and ack back immediately */
+                    UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
+                }
+                else
+                {
+                    //UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);//Test Remove later
+                    APPL_TRACE_DEBUG("Av stream already started");
+                    if (btif_media_cb.peer_sep == AVDT_TSEP_SNK)
+                        btif_a2dp_encoder_update();
+                    if (btif_media_cb.tx_start_initiated == TRUE) {
+                        APPL_TRACE_DEBUG("VSC exchange alreday started on Handoff Start, wait");
+                        break;
+                    }
+                    else if (btif_media_cb.tx_started == FALSE) {
+                        APPL_TRACE_DEBUG("Start VSC exchange on MM Start when state is remote started");
+                        btif_media_on_start_vendor_command();
+                        break;
+                    }
+                }
+                btif_av_reset_reconfig_flag();
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+            }
+            else if (btif_av_stream_ready() == TRUE)
             {
                 /* setup audio data channel listener */
-                UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
-
+                if (!bt_split_a2dp_enabled)
+                {
+                    /* already started, setup audio data channel listener
+                    * and ack back immediately */
+                    UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
+                }
+                else
+                {
+                    APPL_TRACE_DEBUG("Av stream ready");
+                }
                 /* post start event and wait for audio path to open */
                 btif_dispatch_sm_event(BTIF_AV_START_STREAM_REQ_EVT, NULL, 0);
 
@@ -711,14 +933,6 @@
                     a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
 #endif
             }
-            else if (btif_av_stream_started_ready())
-            {
-                /* already started, setup audio data channel listener
-                   and ack back immediately */
-                UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
-
-                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
-            }
             else
             {
                 APPL_TRACE_WARNING("%s: A2DP command %s while AV stream is not ready",
@@ -729,22 +943,35 @@
             break;
 
         case A2DP_CTRL_CMD_STOP:
-            if (btif_media_cb.peer_sep == AVDT_TSEP_SNK &&
-                (!alarm_is_scheduled(btif_media_cb.media_alarm)))
+            if ((!bt_split_a2dp_enabled && btif_media_cb.peer_sep == AVDT_TSEP_SNK &&
+                 (!alarm_is_scheduled(btif_media_cb.media_alarm))) ||
+                (bt_split_a2dp_enabled &&  btif_media_cb.peer_sep == AVDT_TSEP_SNK &&
+                 btif_media_cb.tx_started == FALSE))
             {
                 /* we are already stopped, just ack back */
                 a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
                 break;
             }
 
+            APPL_TRACE_DEBUG("Stop stream request to Av");
             btif_dispatch_sm_event(BTIF_AV_STOP_STREAM_REQ_EVT, NULL, 0);
+
             a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
             break;
 
         case A2DP_CTRL_CMD_SUSPEND:
             /* local suspend */
-            if (btif_av_stream_started_ready())
+            APPL_TRACE_DEBUG("%s:A2DP command %s AV stream_started_ready %d",
+                             __func__, dump_a2dp_ctrl_event(cmd),btif_av_stream_started_ready());
+            if (bt_split_a2dp_enabled && reconfig_a2dp)
             {
+                APPL_TRACE_DEBUG("Suspend called due to reconfig");
+                APPL_TRACE_DEBUG("VS exchange started: ACK suspend, cmd_start will block");
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+            }
+            else if (btif_av_stream_started_ready())
+            {
+                APPL_TRACE_DEBUG("Suspend stream request to Av");
                 btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
             }
             else
@@ -752,6 +979,8 @@
                 /* if we are not in started state, just ack back ok and let
                    audioflinger close the channel. This can happen if we are
                    remotely suspended, clear REMOTE SUSPEND Flag */
+                APPL_TRACE_DEBUG("%s:A2DP command %s AV stream_started_ready clear flag",
+                             __func__, dump_a2dp_ctrl_event(cmd));
                 btif_av_clear_remote_suspend_flag();
                 a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
             }
@@ -767,24 +996,198 @@
             UIPC_Send(UIPC_CH_ID_AV_CTRL, 0, &channel_count, 1);
             break;
         }
-
         case A2DP_CTRL_CMD_OFFLOAD_START:
                 btif_dispatch_sm_event(BTIF_AV_OFFLOAD_START_REQ_EVT, NULL, 0);
             break;
+        case A2DP_CTRL_GET_CODEC_CONFIG:
+        {
+            UINT16 min_mtu;
+            uint8_t param[MAX_CODEC_CFG_SIZE],idx,bta_hdl,codec_id = 0;
+            uint32_t bitrate = 0;
+            uint8_t i = 0;
+            UIPC_Read(UIPC_CH_ID_AV_CTRL, NULL, &idx, 1);
+            memset(param,0,MAX_CODEC_CFG_SIZE);
 
+            if ((btif_av_stream_started_ready() == FALSE) ||
+                (enc_update_in_progress == TRUE))
+            {
+                BTIF_TRACE_ERROR("A2DP_CTRL_GET_CODEC_CONFIG: stream not started");
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+                break;
+            }
+            /*
+            If multicast is supported, codec config will be queried
+            successively for num of playing devices
+            */
+            if (multicast_query)
+            {
+                if (idx == (btif_max_av_clients-1))
+                {
+                    multicast_query = FALSE;
+                    //Get AV handle of index 1
+                }
+                BTIF_TRACE_DEBUG("Mulitcast Enabled, querying index =%d",idx);
+
+                bta_hdl = btif_av_get_av_hdl_from_idx(idx);
+                if (bta_hdl < 0)
+                {
+                    a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+                    break;
+                }
+                //TODO Maintain selected codec info for Multicast with different codecs
+            }
+            else //get playing device hdl
+            {
+                codec_id =  bta_av_co_get_current_codec();
+            }
+
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+            BTIF_TRACE_DEBUG("codec_id = %x",codec_id);
+
+            if (get_soc_type() == BT_SOC_SMD)
+            {
+                //For Pronto PLs Audio pumps raw PCM data for others its encoded data to SOC
+                param[1] = 4; //RAW PCM
+                param[2] = AVDT_MEDIA_AUDIO;
+                param[3] = BTIF_AV_CODEC_PCM;
+                param[4] = btif_media_cb.media_feeding.cfg.pcm.sampling_freq;
+                param[5] = btif_media_cb.media_feeding.cfg.pcm.num_channel;
+            }
+            else if (codec_id == BTIF_AV_CODEC_SBC)
+            {
+                tA2D_SBC_CIE codec_cfg;
+                bta_av_co_audio_get_sbc_config(&codec_cfg, &min_mtu);
+                A2D_BldSbcInfo(AVDT_MEDIA_AUDIO,&codec_cfg,&param[1]);
+                bitrate = btif_media_cb.encoder.u16BitRate * 1000;
+            }
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+            else if (codec_id == BTIF_AV_CODEC_M24) {
+                tA2D_AAC_CIE aac_cfg;
+                bta_av_co_audio_get_aac_config(&aac_cfg, &min_mtu);
+                A2D_BldAacInfo(AVDT_MEDIA_AUDIO,&aac_cfg,&param[1]);
+                bitrate = btif_media_cb.encoder.u16BitRate * 1000;
+            }
+#endif
+            else if (codec_id == A2D_NON_A2DP_MEDIA_CT) //this is changed to non-a2dp VS codec
+            {
+               //ADD APTX support
+                UINT8* ptr = bta_av_co_get_current_codecInfo();
+                int j;
+                UINT8 *p_ptr = ptr;
+                for(j=0; j< (int)sizeof(tA2D_APTX_CIE);j++)
+                {
+                    BTIF_TRACE_DEBUG("codec[%d] = %x",j,*p_ptr++);
+                }
+                if (ptr)
+                {
+                    tA2D_APTX_CIE* codecInfo = 0;
+                    codecInfo = (tA2D_APTX_CIE*) &ptr[BTA_AV_CFG_START_IDX];
+                    if (codecInfo && codecInfo->vendorId == A2D_APTX_VENDOR_ID
+                        && codecInfo->codecId == A2D_APTX_CODEC_ID_BLUETOOTH)
+                    {
+                        tA2D_APTX_CIE aptx_config;
+                        memset(&aptx_config,0,sizeof(tA2D_APTX_CIE));
+                        aptx_config.vendorId = codecInfo->vendorId;
+                        aptx_config.codecId = codecInfo->codecId;
+                        //SampleRate & Chmode are bitmasked
+                        aptx_config.sampleRate = (codecInfo->sampleRate & 0xF0);
+                        aptx_config.channelMode = (codecInfo->sampleRate & 0x0F);
+                        BTIF_TRACE_DEBUG("vendor id = %x",aptx_config.vendorId);
+                        BTIF_TRACE_DEBUG("codec id = %x",aptx_config.codecId);
+                        BTIF_TRACE_DEBUG("sample rate  = %x",aptx_config.sampleRate);
+                        BTIF_TRACE_DEBUG("ch mode  = %x",aptx_config.channelMode);
+                        A2D_BldAptxInfo(AVDT_MEDIA_AUDIO,&aptx_config,&param[1]);
+
+                        /* For aptxClassic BR = (Sampl_Rate * PCM_DEPTH * CHNL)/Compression_Ratio */
+                        bitrate = ((btif_media_cb.media_feeding.cfg.pcm.sampling_freq * 16 * 2)/4);
+                    } else {
+                        tA2D_APTX_HD_CIE* cI = 0;
+                        cI = (tA2D_APTX_HD_CIE*) &ptr[BTA_AV_CFG_START_IDX];
+                        if (cI && cI->vendorId == A2D_APTX_HD_VENDOR_ID
+                        && cI->codecId == A2D_APTX_HD_CODEC_ID_BLUETOOTH)
+                        {
+                            tA2D_APTX_HD_CIE aptxhd_config;
+                            memset(&aptxhd_config,0,sizeof(tA2D_APTX_HD_CIE));
+                            aptxhd_config.vendorId = codecInfo->vendorId;
+                            aptxhd_config.codecId = codecInfo->codecId;
+                            //SampleRate & Chmode are bitmasked
+                            aptxhd_config.sampleRate = (codecInfo->sampleRate & 0xF0);
+                            aptxhd_config.channelMode = (codecInfo->sampleRate & 0x0F);
+                            BTIF_TRACE_DEBUG("vendor id = %x",aptxhd_config.vendorId);
+                            BTIF_TRACE_DEBUG("codec id = %x",aptxhd_config.codecId);
+                            BTIF_TRACE_DEBUG("sample rate  = %x",aptxhd_config.sampleRate);
+                            BTIF_TRACE_DEBUG("ch mode  = %x",aptxhd_config.channelMode);
+                            A2D_BldAptx_hdInfo(AVDT_MEDIA_AUDIO,&aptxhd_config,&param[1]);
+
+                            /* For aptxHD BR = (Sampl_Rate * PCM_DEPTH * CHNL)/Compression_Ratio,
+                               derived from classic */
+                            bitrate = ((btif_media_cb.media_feeding.cfg.pcm.sampling_freq * 24 * 2)/4);
+                       }
+                   }
+                }
+            }
+            param[0] = btif_get_latest_playing_device_idx();
+            i = param[1] + 2; //LOSC
+            param[i++] = (UINT8)(btif_media_cb.TxAaMtuSize & 0x00FF);
+            param[i++] = (UINT8)(((btif_media_cb.TxAaMtuSize & 0xFF00) >> 8) & 0x00FF);
+            param[i++] = (UINT8)(bitrate & 0x00FF);
+            param[i++] = (UINT8)(((bitrate & 0xFF00) >> 8) & 0x00FF);
+            param[i++] = (UINT8)(((bitrate & 0xFF0000) >> 16) & 0x00FF);
+            param[i++] = (UINT8)(((bitrate & 0xFF000000) >> 24) & 0x00FF);
+            UIPC_Send(UIPC_CH_ID_AV_CTRL, 0, &i, 1);
+            UIPC_Send(UIPC_CH_ID_AV_CTRL, 0, (UINT8 *)&param, i);
+            break;
+        }
+
+        case A2DP_CTRL_GET_MULTICAST_STATUS:
+        {
+            uint8_t playing_devices = (uint8_t)btif_av_get_num_playing_devices();
+            BOOLEAN multicast_state = btif_av_get_multicast_state();
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+            multicast_query = FALSE;
+            if ((btif_max_av_clients > 1 && playing_devices == btif_max_av_clients) &&
+                multicast_state)
+            {
+                multicast_query = TRUE;
+            }
+            BTIF_TRACE_ERROR("multicast status = %d",multicast_query);
+            UIPC_Send(UIPC_CH_ID_AV_CTRL, 0, &multicast_query, 1);
+            UIPC_Send(UIPC_CH_ID_AV_CTRL, 0, &playing_devices, 1);
+
+            break;
+        }
+        case A2DP_CTRL_CMD_OFFLOAD_SUPPORTED:
+            BTIF_TRACE_ERROR("Split A2DP supported");
+            bt_split_a2dp_enabled = TRUE;
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+            break;
+        case A2DP_CTRL_CMD_OFFLOAD_NOT_SUPPORTED:
+            BTIF_TRACE_ERROR("Split A2DP not supported");
+            bt_split_a2dp_enabled = FALSE; //Change to FALSE later
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+            break;
+        case A2DP_CTRL_GET_CONNECTION_STATUS:
+            if (btif_av_is_connected() && media_task_running != MEDIA_TASK_STATE_SHUTTING_DOWN)
+            {
+                BTIF_TRACE_DEBUG("got valid connection");
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+            }
+            else
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+            break;
         default:
             APPL_TRACE_ERROR("UNSUPPORTED CMD (%d)", cmd);
             a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
             break;
     }
-    APPL_TRACE_DEBUG("a2dp-ctrl-cmd : %s DONE", dump_a2dp_ctrl_event(cmd));
+    APPL_TRACE_IMP("a2dp-ctrl-cmd : %s DONE", dump_a2dp_ctrl_event(cmd));
 }
 
 static void btif_a2dp_ctrl_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event)
 {
     UNUSED(ch_id);
 
-    APPL_TRACE_DEBUG("A2DP-CTRL-CHANNEL EVENT %s", dump_uipc_event(event));
+    APPL_TRACE_IMP("A2DP-CTRL-CHANNEL EVENT %s", dump_uipc_event(event));
 
     switch (event)
     {
@@ -826,11 +1229,9 @@
                        (void *)A2DP_DATA_READ_POLL_MS);
 
             if (btif_media_cb.peer_sep == AVDT_TSEP_SNK) {
-                /* Start the media task to encode SBC */
-                btif_media_task_start_aa_req();
-
                 /* make sure we update any changed sbc encoder params */
-                btif_a2dp_encoder_update();
+                /*post a message to btif_av to serialize encode update and encode init*/
+                btif_dispatch_sm_event(BTIF_AV_UPDATE_ENCODER_REQ_EVT, NULL, 0);
             }
             btif_media_cb.data_channel_open = TRUE;
 
@@ -849,6 +1250,45 @@
     }
 }
 
+static BOOLEAN btif_media_task_is_aptx_configured()
+{
+    BOOLEAN result = FALSE;
+    UINT8 codectype = bta_av_co_get_current_codec();
+
+    if (codectype == A2D_NON_A2DP_MEDIA_CT) {
+        UINT8* ptr = bta_av_co_get_current_codecInfo();
+        if (ptr) {
+            tA2D_APTX_CIE* codecInfo = (tA2D_APTX_CIE*) &ptr[BTA_AV_CFG_START_IDX];
+            /* Fix for below Klockwork Issue.
+             * Pointer 'codecInfo' checked for NULL at line 1089 may be dereferenced at line 1092.*/
+            if ((codecInfo && codecInfo->vendorId == A2D_APTX_VENDOR_ID && codecInfo->codecId == A2D_APTX_CODEC_ID_BLUETOOTH)
+                || (codecInfo && codecInfo->vendorId == A2D_APTX_HD_VENDOR_ID && codecInfo->codecId == A2D_APTX_HD_CODEC_ID_BLUETOOTH)) {
+                APPL_TRACE_DEBUG("%s codecId %d", __func__, codecInfo->codecId);
+                APPL_TRACE_DEBUG("%s vendorId %x", __func__, codecInfo->vendorId);
+                result = TRUE;
+            }
+        }
+    }
+    return result;
+}
+
+A2D_AptXCodecType btif_media_task_get_aptX_codec_type()
+{
+    A2D_AptXCodecType codec = APTX_CODEC_NONE;
+    UINT8 a2dp_codectype = bta_av_co_get_current_codec();
+
+    if (a2dp_codectype == A2D_NON_A2DP_MEDIA_CT) {
+        UINT8* ptr = bta_av_co_get_current_codecInfo();
+        if (ptr) {
+            tA2D_APTX_CIE* codecInfo = (tA2D_APTX_CIE*) &ptr[BTA_AV_CFG_START_IDX];
+            if (codecInfo && codecInfo->vendorId == A2D_APTX_VENDOR_ID && codecInfo->codecId == A2D_APTX_CODEC_ID_BLUETOOTH)
+                codec = APTX_CODEC;
+            else if (codecInfo && codecInfo->vendorId == A2D_APTX_HD_VENDOR_ID && codecInfo->codecId == A2D_APTX_HD_CODEC_ID_BLUETOOTH)
+                codec = APTX_HD_CODEC;
+        }
+    }
+    return codec;
+}
 
 /*****************************************************************************
  **  BTIF ADAPTATION
@@ -868,12 +1308,15 @@
     return rate;
 }
 
-static void btif_a2dp_encoder_init(void)
+static void btif_a2dp_encoder_init(tBTA_AV_HNDL hdl)
 {
     UINT16 minmtu;
     tBTIF_MEDIA_INIT_AUDIO msg;
     tA2D_SBC_CIE sbc_config;
-
+    tA2D_APTX_CIE* codecInfo = 0;
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    tA2D_AAC_CIE aac_config;
+#endif
     /* lookup table for converting channel mode */
     UINT16 codec_mode_tbl[5] = { SBC_JOINT_STEREO, SBC_STEREO, SBC_DUAL, 0, SBC_MONO };
 
@@ -885,14 +1328,92 @@
 
     APPL_TRACE_DEBUG("btif_a2dp_encoder_init");
 
+    btif_media_cb.aptxEncoderParams.encoder = 0;
+
+    memset(&msg, 0, sizeof(msg));
+#if (BTA_AV_CO_CP_SCMS_T == TRUE)
+    ALOGI("%s SCMS_T ENABLED", __func__);
+#else
+    ALOGI("%s SCMS_T DISABLED", __func__);
+#endif
+
+    UINT8 codectype;
+    codectype = bta_av_select_codec(hdl);
+    if (A2D_NON_A2DP_MEDIA_CT == codectype) {
+        UINT8* ptr = bta_av_co_get_current_codecInfo();
+        if (ptr) {
+           //tA2D_APTX_CIE starts on 4th byte
+            codecInfo = (tA2D_APTX_CIE*) &ptr[BTA_AV_CFG_START_IDX];
+            APPL_TRACE_DEBUG("%s codecId = %d", __func__, codecInfo->codecId);
+            APPL_TRACE_DEBUG("%s vendorId = %x", __func__, codecInfo->vendorId);
+
+            if (codecInfo && codecInfo->vendorId == A2D_APTX_VENDOR_ID
+                    && codecInfo->codecId == A2D_APTX_CODEC_ID_BLUETOOTH)
+            {
+                btif_media_cb.offset = BTIF_MEDIA_AA_APTX_OFFSET;
+                tA2D_APTX_CIE aptx_config;
+                ALOGI("%s Selected Codec aptX", __func__);
+                aptx_config.vendorId = codecInfo->vendorId;
+                aptx_config.codecId = codecInfo->codecId;
+                bta_av_co_audio_get_codec_config((UINT8*)&aptx_config, &minmtu, A2D_NON_A2DP_MEDIA_CT);
+                msg.CodecType = A2D_NON_A2DP_MEDIA_CT;
+                msg.SamplingFreq = aptx_config.sampleRate;
+                msg.MtuSize = minmtu;
+                msg.ChannelMode = aptx_config.channelMode;
+                msg.BluetoothVendorID = aptx_config.vendorId;
+                msg.BluetoothCodecID = aptx_config.codecId;
+                btif_media_task_enc_init_req(&msg);
+                return;
+            }
+
+            if (codecInfo && codecInfo->vendorId == A2D_APTX_HD_VENDOR_ID
+                && codecInfo->codecId == A2D_APTX_HD_CODEC_ID_BLUETOOTH)
+            {
+                btif_media_cb.offset = BTIF_MEDIA_AA_APTX_HD_OFFSET;
+                tA2D_APTX_HD_CIE aptx_hd_config;
+                ALOGI("%s Selected Codec aptX HD", __func__);
+                aptx_hd_config.vendorId = codecInfo->vendorId;
+                aptx_hd_config.codecId = codecInfo->codecId;
+                bta_av_co_audio_get_codec_config((UINT8*)&aptx_hd_config, &minmtu, A2D_NON_A2DP_MEDIA_CT);
+                msg.CodecType = A2D_NON_A2DP_MEDIA_CT;
+                msg.SamplingFreq = aptx_hd_config.sampleRate;
+                msg.MtuSize = minmtu;
+                msg.ChannelMode = aptx_hd_config.channelMode;
+                msg.BluetoothVendorID = aptx_hd_config.vendorId;
+                msg.BluetoothCodecID = aptx_hd_config.codecId;
+                btif_media_task_enc_init_req(&msg);
+                return;
+            }
+        }
+    }/* if ( A2D_NON_A2DP_MEDIA_CT == codectype) */
+
+
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    if (BTIF_AV_CODEC_M24 == codectype) {
+        ALOGI("%s Selected Codec AAC", __func__);
+        bta_av_co_audio_get_codec_config ((UINT8*)&aac_config, &minmtu, BTIF_AV_CODEC_M24);
+        msg.ObjectType = aac_config.object_type;
+        msg.ChannelMode = (aac_config.channels == A2D_AAC_IE_CHANNELS_2) ? SBC_STEREO : SBC_MONO;
+        msg.SamplingFreq =  freq_block_tbl[aac_config.samp_freq >> 5];
+        msg.MtuSize = minmtu;
+        msg.CodecType = BTIF_AV_CODEC_M24;
+        msg.bit_rate = aac_config.bit_rate;
+        btif_media_task_enc_init_req(&msg);
+        return;
+    }
+#endif
+
+    ALOGI("%s Selected Codec SBC", __func__);
+
     /* Retrieve the current SBC configuration (default if currently not used) */
-    bta_av_co_audio_get_sbc_config(&sbc_config, &minmtu);
+    bta_av_co_audio_get_codec_config((UINT8*)&sbc_config, &minmtu, BTIF_AV_CODEC_SBC);
     msg.NumOfSubBands = (sbc_config.num_subbands == A2D_SBC_IE_SUBBAND_4) ? 4 : 8;
     msg.NumOfBlocks = codec_block_tbl[sbc_config.block_len >> 5];
     msg.AllocationMethod = (sbc_config.alloc_mthd == A2D_SBC_IE_ALLOC_MD_L) ? SBC_LOUDNESS : SBC_SNR;
     msg.ChannelMode = codec_mode_tbl[sbc_config.ch_mode >> 1];
     msg.SamplingFreq = freq_block_tbl[sbc_config.samp_freq >> 5];
     msg.MtuSize = minmtu;
+    msg.CodecType = BTIF_AV_CODEC_SBC;
 
     APPL_TRACE_EVENT("msg.ChannelMode %x", msg.ChannelMode);
 
@@ -902,51 +1423,112 @@
 
 static void btif_a2dp_encoder_update(void)
 {
-    UINT16 minmtu;
+    UINT16 minmtu = 0;
     tA2D_SBC_CIE sbc_config;
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    tA2D_AAC_CIE aac_config;
+#endif
     tBTIF_MEDIA_UPDATE_AUDIO msg;
     UINT8 pref_min;
     UINT8 pref_max;
+    tA2D_APTX_CIE* codecInfo = 0;
 
     APPL_TRACE_DEBUG("btif_a2dp_encoder_update");
+    btif_media_cb.tx_enc_update_initiated = TRUE;
 
-    /* Retrieve the current SBC configuration (default if currently not used) */
-    bta_av_co_audio_get_sbc_config(&sbc_config, &minmtu);
-
-    APPL_TRACE_DEBUG("btif_a2dp_encoder_update: Common min_bitpool:%d(0x%x) max_bitpool:%d(0x%x)",
-            sbc_config.min_bitpool, sbc_config.min_bitpool,
-            sbc_config.max_bitpool, sbc_config.max_bitpool);
-
-    if (sbc_config.min_bitpool > sbc_config.max_bitpool)
+    UINT8 codectype = 0;
+    codectype = bta_av_co_get_current_codec();
+    enc_update_in_progress = TRUE;
+    if (codectype == A2D_NON_A2DP_MEDIA_CT)
     {
-        APPL_TRACE_ERROR("btif_a2dp_encoder_update: ERROR btif_a2dp_encoder_update min_bitpool > max_bitpool");
-    }
-
-    /* check if remote sink has a preferred bitpool range */
-    if (bta_av_co_get_remote_bitpool_pref(&pref_min, &pref_max) == TRUE)
-    {
-        /* adjust our preferred bitpool with the remote preference if within
-           our capable range */
-
-        if (pref_min < sbc_config.min_bitpool)
-            pref_min = sbc_config.min_bitpool;
-
-        if (pref_max > sbc_config.max_bitpool)
-            pref_max = sbc_config.max_bitpool;
-
-        msg.MinBitPool = pref_min;
-        msg.MaxBitPool = pref_max;
-
-        if ((pref_min != sbc_config.min_bitpool) || (pref_max != sbc_config.max_bitpool))
+        UINT8* ptr = bta_av_co_get_current_codecInfo();
+        if (ptr)
         {
-            APPL_TRACE_EVENT("## adjusted our bitpool range to peer pref [%d:%d] ##",
-                pref_min, pref_max);
-        }
+            codecInfo = (tA2D_APTX_CIE*) &ptr[BTA_AV_CFG_START_IDX];
+            if (codecInfo && codecInfo->vendorId == A2D_APTX_VENDOR_ID && codecInfo->codecId == A2D_APTX_CODEC_ID_BLUETOOTH)
+            {
+                APPL_TRACE_DEBUG("%s aptX", __func__);
+                tA2D_APTX_CIE aptx_config;
+                aptx_config.vendorId = codecInfo->vendorId;
+                aptx_config.codecId = codecInfo->codecId;
+                bta_av_co_audio_get_codec_config((UINT8*)&aptx_config, &minmtu, A2D_NON_A2DP_MEDIA_CT );
+                msg.CodecType = A2D_NON_A2DP_MEDIA_CT;
+                msg.BluetoothVendorID = aptx_config.vendorId;
+                msg.BluetoothCodecID = aptx_config.codecId;
+            }
+
+            if (codecInfo && codecInfo->vendorId == A2D_APTX_HD_VENDOR_ID && codecInfo->codecId == A2D_APTX_HD_CODEC_ID_BLUETOOTH)
+            {
+                APPL_TRACE_DEBUG("%s aptX HD", __func__);
+                tA2D_APTX_HD_CIE aptx_hd_config;
+                aptx_hd_config.vendorId = codecInfo->vendorId;
+                aptx_hd_config.codecId = codecInfo->codecId;
+                bta_av_co_audio_get_codec_config((UINT8*)&aptx_hd_config, &minmtu, A2D_NON_A2DP_MEDIA_CT );
+                msg.CodecType = A2D_NON_A2DP_MEDIA_CT;
+                msg.BluetoothVendorID = aptx_hd_config.vendorId;
+                msg.BluetoothCodecID = aptx_hd_config.codecId;
+            }
+        } /* if (ptr) */
     }
-    else
-    {
-        msg.MinBitPool = sbc_config.min_bitpool;
-        msg.MaxBitPool = sbc_config.max_bitpool;
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    else if (codectype == BTIF_AV_CODEC_M24) {
+        bta_av_co_audio_get_aac_config(&aac_config, &minmtu);
+
+        APPL_TRACE_DEBUG("btif_a2dp_encoder_update: AAC object_type :%d channels :%d",
+                aac_config.object_type, aac_config.channels);
+        msg.CodecType = BTIF_AV_CODEC_M24;
+    }
+#endif
+    else {
+
+        /* Retrieve the current SBC configuration (default if currently not used) */
+        bta_av_co_audio_get_sbc_config(&sbc_config, &minmtu);
+
+        APPL_TRACE_DEBUG("btif_a2dp_encoder_update: Common min_bitpool:%d(0x%x) max_bitpool:%d(0x%x)",
+                sbc_config.min_bitpool, sbc_config.min_bitpool,
+                sbc_config.max_bitpool, sbc_config.max_bitpool);
+
+        if (sbc_config.min_bitpool > sbc_config.max_bitpool)
+        {
+            APPL_TRACE_ERROR("btif_a2dp_encoder_update: ERROR btif_a2dp_encoder_update min_bitpool > max_bitpool");
+        }
+
+        /* check if remote sink has a preferred bitpool range */
+        if (bta_av_co_get_remote_bitpool_pref(&pref_min, &pref_max) == TRUE)
+        {
+            /* adjust our preferred bitpool with the remote preference if within
+               our capable range */
+
+            if (pref_min < sbc_config.min_bitpool)
+                pref_min = sbc_config.min_bitpool;
+
+            if ((pref_max > sbc_config.max_bitpool) || (pref_max == 0))
+                pref_max = sbc_config.max_bitpool;
+
+            msg.MinBitPool = pref_min;
+            msg.MaxBitPool = pref_max;
+
+            if ((pref_min != sbc_config.min_bitpool) || (pref_max != sbc_config.max_bitpool))
+            {
+                APPL_TRACE_EVENT("## adjusted our bitpool range to peer pref [%d:%d] ##",
+                    pref_min, pref_max);
+            }
+        }
+        else
+        {
+            msg.MinBitPool = sbc_config.min_bitpool;
+            msg.MaxBitPool = sbc_config.max_bitpool;
+        }
+
+        msg.CodecType = BTIF_AV_CODEC_SBC;
+
+        if (bt_split_a2dp_enabled)
+        {
+            btif_media_cb.max_bitpool = msg.MaxBitPool;
+            btif_media_cb.min_bitpool = msg.MinBitPool;
+            APPL_TRACE_DEBUG("Updated min_bitpool: 0x%x max_bitpool: 0x%x",
+                btif_media_cb.min_bitpool, btif_media_cb.max_bitpool);
+        }
     }
 
     msg.MinMtuSize = minmtu;
@@ -955,6 +1537,17 @@
     btif_media_task_enc_update_req(&msg);
 }
 
+bool btif_a2dp_is_media_task_stopped(void)
+{
+    if (media_task_running != MEDIA_TASK_STATE_OFF)
+    {
+        APPL_TRACE_ERROR("btif_a2dp_is_media_task_stopped: %d",
+                                            media_task_running);
+        return false;
+    }
+    return true;
+}
+
 bool btif_a2dp_start_media_task(void)
 {
     if (media_task_running != MEDIA_TASK_STATE_OFF)
@@ -963,12 +1556,14 @@
         return false;
     }
 
-    APPL_TRACE_EVENT("## A2DP START MEDIA THREAD ##");
+    APPL_TRACE_IMP("## A2DP START MEDIA THREAD ##");
 
     btif_media_cmd_msg_queue = fixed_queue_new(SIZE_MAX);
+    if (btif_media_cmd_msg_queue == NULL)
+        goto error_exit;
 
     /* start a2dp media task */
-    worker_thread = thread_new("media_worker");
+    worker_thread = thread_new_sized("media_worker", MAX_MEDIA_WORKQUEUE_SEM_COUNT);
     if (worker_thread == NULL)
         goto error_exit;
 
@@ -978,7 +1573,7 @@
         NULL);
 
     thread_post(worker_thread, btif_media_thread_init, NULL);
-    APPL_TRACE_EVENT("## A2DP MEDIA THREAD STARTED ##");
+    APPL_TRACE_IMP("## A2DP MEDIA THREAD STARTED ##");
 
     return true;
 
@@ -989,18 +1584,37 @@
 
 void btif_a2dp_stop_media_task(void)
 {
-    APPL_TRACE_EVENT("## A2DP STOP MEDIA THREAD ##");
+    APPL_TRACE_DEBUG("## A2DP STOP MEDIA THREAD ##");
+    if (media_task_running != MEDIA_TASK_STATE_ON)
+    {
+        APPL_TRACE_ERROR("warning: media task cleanup state: %d",
+                                        media_task_running);
+        return;
+    }
+    /* make sure no channels are restarted while shutting down */
+    media_task_running = MEDIA_TASK_STATE_SHUTTING_DOWN;
+
+    // remove aptX thread
+    A2D_stop_aptX();
 
     // Stop timer
     alarm_free(btif_media_cb.media_alarm);
     btif_media_cb.media_alarm = NULL;
 
+    if (btif_media_cb.remote_start_alarm != NULL)
+    {
+        alarm_free(btif_media_cb.remote_start_alarm);
+        btif_media_cb.remote_start_alarm = NULL;
+        btif_dispatch_sm_event(BTIF_AV_RESET_REMOTE_STARTED_FLAG_EVT, NULL, 0);
+    }
     // Exit thread
     fixed_queue_free(btif_media_cmd_msg_queue, NULL);
-    btif_media_cmd_msg_queue = NULL;
     thread_post(worker_thread, btif_media_thread_cleanup, NULL);
     thread_free(worker_thread);
+
     worker_thread = NULL;
+    btif_media_cmd_msg_queue = NULL;
+    APPL_TRACE_DEBUG("## A2DP MEDIA THREAD STOPPED ##");
 }
 
 /*****************************************************************************
@@ -1032,7 +1646,7 @@
 **
 *******************************************************************************/
 
-void btif_a2dp_setup_codec(void)
+tBTIF_STATUS btif_a2dp_setup_codec(tBTA_AV_HNDL hdl)
 {
     tBTIF_AV_MEDIA_FEEDINGS media_feeding;
     tBTIF_STATUS status;
@@ -1041,18 +1655,28 @@
 
     mutex_global_lock();
 
-    /* for now hardcode 44.1 khz 16 bit stereo PCM format */
+
+#ifdef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
+    /* for now hardcode 48 khz 16 bit stereo PCM format */
+    media_feeding.cfg.pcm.sampling_freq = 48000;
+#else
+    /* for now hardcode 44.1 khz 32 bit stereo PCM format */
     media_feeding.cfg.pcm.sampling_freq = BTIF_A2DP_SRC_SAMPLING_RATE;
+#endif
     media_feeding.cfg.pcm.bit_per_sample = BTIF_A2DP_SRC_BIT_DEPTH;
     media_feeding.cfg.pcm.num_channel = BTIF_A2DP_SRC_NUM_CHANNELS;
     media_feeding.format = BTIF_AV_CODEC_PCM;
 
+    /* 32 bits for AUDIO_FORMAT_PCM_8_24_BIT, all codecs affected. */
+    APPL_TRACE_EVENT("%s bit_per_sample %d", __func__, media_feeding.cfg.pcm.bit_per_sample);
+    APPL_TRACE_EVENT("%s sampling_freq %d", __func__, media_feeding.cfg.pcm.sampling_freq);
+
     if (bta_av_co_audio_set_codec(&media_feeding, &status))
     {
         tBTIF_MEDIA_INIT_AUDIO_FEEDING mfeed;
 
         /* Init the encoding task */
-        btif_a2dp_encoder_init();
+        btif_a2dp_encoder_init(hdl);
 
         /* Build the media task configuration */
         mfeed.feeding = media_feeding;
@@ -1060,8 +1684,33 @@
         /* Send message to Media task to configure transcoding */
         btif_media_task_audio_feeding_init_req(&mfeed);
     }
+    else
+    {
+        status = BTIF_ERROR_SRV_AV_FEEDING_NOT_SUPPORTED;
+    }
 
     mutex_global_unlock();
+        return status;
+}
+
+
+/*****************************************************************************
+**
+** Function        btif_a2dp_update_codec
+**
+** Description
+**
+** Returns
+**
+*******************************************************************************/
+
+void btif_a2dp_update_codec(void)
+{
+    APPL_TRACE_DEBUG("## A2DP UPDATE CODEC ##");
+    mutex_global_lock();
+    btif_media_task_start_aa_req();
+    btif_a2dp_encoder_update();
+    mutex_global_unlock();
 }
 
 
@@ -1077,12 +1726,14 @@
 
 void btif_a2dp_on_idle(void)
 {
-    APPL_TRACE_EVENT("## ON A2DP IDLE ## peer_sep = %d", btif_media_cb.peer_sep);
+    APPL_TRACE_IMP("## ON A2DP IDLE ## peer_sep = %d", btif_media_cb.peer_sep);
     if (btif_media_cb.peer_sep == AVDT_TSEP_SNK)
     {
         /* Make sure media task is stopped */
         btif_media_task_stop_aa_req();
     }
+    if (bt_split_a2dp_enabled)
+        btif_media_send_reset_vendor_state();
 
     bta_av_co_init();
 #if (BTA_AV_SINK_INCLUDED == TRUE)
@@ -1109,10 +1760,11 @@
 
 void btif_a2dp_on_open(void)
 {
-    APPL_TRACE_EVENT("## ON A2DP OPEN ##");
+    APPL_TRACE_IMP("## ON A2DP OPEN ##");
 
     /* always use callback to notify socket events */
-    UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
+    if (!bt_split_a2dp_enabled)
+        UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
 }
 
 /*******************************************************************************
@@ -1126,10 +1778,11 @@
  *******************************************************************************/
 BOOLEAN btif_media_task_clear_track(void)
 {
-    BT_HDR *p_buf = osi_malloc(sizeof(BT_HDR));
+    BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
 
     p_buf->event = BTIF_MEDIA_AUDIO_SINK_CLEAR_TRACK;
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 
     return TRUE;
 }
@@ -1156,8 +1809,8 @@
 
     memcpy(p_buf->codec_info,p_av, AVDT_CODEC_SIZE);
     p_buf->hdr.event = BTIF_MEDIA_AUDIO_SINK_CFG_UPDATE;
-
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 }
 
 /*****************************************************************************
@@ -1170,16 +1823,28 @@
 **
 *******************************************************************************/
 
-BOOLEAN btif_a2dp_on_started(tBTA_AV_START *p_av, BOOLEAN pending_start)
+BOOLEAN btif_a2dp_on_started(tBTA_AV_START *p_av, BOOLEAN pending_start, tBTA_AV_HNDL hdl)
 {
     BOOLEAN ack = FALSE;
 
-    APPL_TRACE_EVENT("## ON A2DP STARTED ##");
+    APPL_TRACE_IMP("## ON A2DP STARTED ##");
 
     if (p_av == NULL)
     {
-        /* ack back a local start request */
-        a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+        if (bt_split_a2dp_enabled)
+        {
+            APPL_TRACE_EVENT("## ON A2DP STARTED  split a2dp enabled##");
+            if (btif_media_cb.peer_sep == AVDT_TSEP_SNK)
+            {
+                btif_media_on_start_vendor_command();
+            }
+        }
+        else
+        {
+            /* ack back a local start request */
+            if (btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_START)
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+        }
         return TRUE;
     }
 
@@ -1190,7 +1855,18 @@
             if (p_av->initiator)
             {
                 if (pending_start) {
-                    a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+                    if (bt_split_a2dp_enabled)
+                    {
+                        if (btif_media_cb.peer_sep == AVDT_TSEP_SNK)
+                        {
+                            btif_media_on_start_vendor_command();
+                        }
+                    }
+                    else
+                    {
+                        if (btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_START)
+                            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+                    }
                     ack = TRUE;
                 }
             }
@@ -1198,7 +1874,16 @@
             {
                 /* we were remotely started,  make sure codec
                    is setup before datapath is started */
-                btif_a2dp_setup_codec();
+                if (bt_split_a2dp_enabled)
+                {
+                    if (btif_media_cb.peer_sep == AVDT_TSEP_SNK)
+                    {
+                        APPL_TRACE_IMP("Do not Initiate VSC exchange on remote start");
+                        //btif_media_on_start_vendor_command();
+                    }
+                }
+                else
+                    btif_a2dp_setup_codec(hdl);
             }
 
             /* media task is autostarted upon a2dp audiopath connection */
@@ -1208,13 +1893,13 @@
     {
         APPL_TRACE_WARNING("%s: A2DP start request failed: status = %d",
                          __func__, p_av->status);
-        a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+        if (btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_START)
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
         ack = TRUE;
     }
     return ack;
 }
 
-
 /*****************************************************************************
 **
 ** Function        btif_a2dp_ack_fail
@@ -1227,7 +1912,7 @@
 
 void btif_a2dp_ack_fail(void)
 {
-    APPL_TRACE_EVENT("## A2DP_CTRL_ACK_FAILURE ##");
+    APPL_TRACE_IMP("## A2DP_CTRL_ACK_FAILURE ##");
     a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
 }
 
@@ -1243,7 +1928,7 @@
 
 void btif_a2dp_on_stopped(tBTA_AV_SUSPEND *p_av)
 {
-    APPL_TRACE_EVENT("## ON A2DP STOPPED ##");
+    APPL_TRACE_IMP("## ON A2DP STOPPED ##");
     if (btif_media_cb.peer_sep == AVDT_TSEP_SRC) /*  Handling for A2DP SINK cases*/
     {
         btif_media_cb.rx_flush = TRUE;
@@ -1265,7 +1950,9 @@
             if (p_av->initiator) {
                 APPL_TRACE_WARNING("%s: A2DP stop request failed: status = %d",
                                    __func__, p_av->status);
-                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+                if ((btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_STOP) ||
+                    (btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_SUSPEND))
+                    a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
             }
             return;
         }
@@ -1275,7 +1962,8 @@
     btif_media_cb.tx_flush = 1;
 
     /* request to stop media task  */
-    btif_media_task_aa_tx_flush_req();
+    if (!bt_split_a2dp_enabled)
+        btif_media_task_aa_tx_flush_req();
     btif_media_task_stop_aa_req();
 
     /* once stream is fully stopped we will ack back */
@@ -1294,7 +1982,7 @@
 
 void btif_a2dp_on_suspended(tBTA_AV_SUSPEND *p_av)
 {
-    APPL_TRACE_EVENT("## ON A2DP SUSPENDED ##");
+    APPL_TRACE_IMP("## ON A2DP SUSPENDED ##");
     if (btif_media_cb.peer_sep == AVDT_TSEP_SRC)
     {
         btif_media_cb.rx_flush = TRUE;
@@ -1312,7 +2000,9 @@
         if (p_av->initiator == TRUE) {
             APPL_TRACE_WARNING("%s: A2DP suspend request failed: status = %d",
                                __func__, p_av->status);
-            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+            if ((btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_STOP) ||
+                    (btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_SUSPEND))
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
         }
     }
 
@@ -1325,9 +2015,83 @@
     btif_media_task_stop_aa_req();
 }
 
+UINT8 btif_a2dp_get_pending_hal_command()
+{
+    return btif_media_cb.a2dp_cmd_pending;
+}
 
 /*****************************************************************************
 **
+** Function        btif_media_remote_start_alarm_cb
+**
+** Description     Remote start honor timer, if media is not started then
+**                 suspend AV
+** Returns
+**
+*******************************************************************************/
+static void btif_media_remote_start_alarm_cb(UNUSED_ATTR void *context) {
+  thread_post(worker_thread, btif_a2dp_remote_start_timer, NULL);
+}
+
+/*****************************************************************************
+**
+** Function        btif_a2dp_remote_start_timer
+**
+** Description     Suspend stream if media is not started for remote stream
+**                 start is honored
+** Returns
+**
+*******************************************************************************/
+void btif_a2dp_remote_start_timer()
+{
+    alarm_free(btif_media_cb.remote_start_alarm);
+    btif_media_cb.remote_start_alarm = NULL;
+    APPL_TRACE_DEBUG("Suspend stream request to Av");
+    btif_dispatch_sm_event(BTIF_AV_REMOTE_SUSPEND_STREAM_REQ_EVT, NULL, 0);
+}
+
+void btif_a2dp_cancel_remote_start_timer()
+{
+    if (alarm_is_scheduled(btif_media_cb.remote_start_alarm))
+    {
+        APPL_TRACE_DEBUG("Cancel remote start timer");
+        alarm_free(btif_media_cb.remote_start_alarm);
+        btif_media_cb.remote_start_alarm = NULL;
+    }
+}
+
+void btif_media_on_cancel_remote_start_alarm() {
+  thread_post(worker_thread, btif_a2dp_cancel_remote_start_timer, NULL);
+}
+
+/*****************************************************************************
+**
+** Function        btif_a2dp_on_remote_started
+**
+** Description
+**
+** Returns
+**
+*******************************************************************************/
+void btif_a2dp_on_remote_started()
+{
+    btif_media_cb.remote_start_alarm = alarm_new("btif.remote_start_task");
+
+    if (!btif_media_cb.remote_start_alarm)
+    {
+        APPL_TRACE_WARNING("%s:unable to allocate media alarm",__func__);
+        return;
+    }
+    alarm_set(btif_media_cb.remote_start_alarm, BTIF_REMOTE_START_TOUT,
+              btif_media_remote_start_alarm_cb, NULL);
+}
+
+BOOLEAN btif_is_remote_start_timer_scheduled()
+{
+    return (alarm_is_scheduled(btif_media_cb.remote_start_alarm))? TRUE:FALSE;
+}
+/*****************************************************************************
+**
 ** Function        btif_a2dp_on_offload_started
 **
 ** Description
@@ -1381,7 +2145,8 @@
 
     p_buf->focus_state = state;
     p_buf->hdr.event = BTIF_MEDIA_AUDIO_SINK_SET_FOCUS_STATE;
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 }
 
 void btif_a2dp_set_audio_track_gain(float gain)
@@ -1499,6 +2264,7 @@
   // we're using that in frame size calculations now.
   assert(CHAR_BIT == 8);
 
+  APPL_TRACE_IMP(" btif_media_thread_init");
   memset(&btif_media_cb, 0, sizeof(btif_media_cb));
 
   UIPC_Init(NULL);
@@ -1511,13 +2277,16 @@
 
   raise_priority_a2dp(TASK_HIGH_MEDIA);
   media_task_running = MEDIA_TASK_STATE_ON;
+  enc_update_in_progress = FALSE;
+  APPL_TRACE_DEBUG(" btif_media_thread_init complete");
   metrics_log_bluetooth_session_start(CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
 }
 
 static void btif_media_thread_cleanup(UNUSED_ATTR void *context) {
-  /* make sure no channels are restarted while shutting down */
-  media_task_running = MEDIA_TASK_STATE_SHUTTING_DOWN;
+  APPL_TRACE_IMP(" btif_media_thread_cleanup");
 
+  APPL_TRACE_IMP(" before close the UIPC channnel, ack the pending cmd");
+  a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
   /* this calls blocks until uipc is fully closed */
   UIPC_Close(UIPC_CH_ID_ALL);
 
@@ -1530,6 +2299,8 @@
 
   /* Clear media task flag */
   media_task_running = MEDIA_TASK_STATE_OFF;
+  enc_update_in_progress = FALSE;
+  APPL_TRACE_DEBUG(" btif_media_thread_cleanup complete");
   metrics_log_bluetooth_session_end(DISCONNECT_REASON_UNKNOWN, 0);
 }
 
@@ -1544,11 +2315,12 @@
  *******************************************************************************/
 BOOLEAN btif_media_task_send_cmd_evt(UINT16 Evt)
 {
-    BT_HDR *p_buf = osi_malloc(sizeof(BT_HDR));
+    BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
 
     p_buf->event = Evt;
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
     return TRUE;
 }
 
@@ -1572,7 +2344,7 @@
 static void btif_media_thread_handle_cmd(fixed_queue_t *queue, UNUSED_ATTR void *context)
 {
     BT_HDR *p_msg = (BT_HDR *)fixed_queue_dequeue(queue);
-    LOG_VERBOSE(LOG_TAG, "btif_media_thread_handle_cmd : %d %s", p_msg->event,
+    APPL_TRACE_IMP("btif_media_thread_handle_cmd : %d %s", p_msg->event,
              dump_media_event(p_msg->event));
 
     switch (p_msg->event)
@@ -1620,12 +2392,189 @@
      case BTIF_MEDIA_FLUSH_AA_RX:
         btif_media_task_aa_rx_flush();
         break;
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+    case BTIF_MEDIA_RESET_VS_STATE:
+        btif_media_cb.tx_started = FALSE;
+        btif_media_cb.tx_stop_initiated = FALSE;
+        btif_media_cb.vs_configs_exchanged = FALSE;
+        btif_media_cb.tx_start_initiated = FALSE;
+        btif_media_cb.tx_enc_update_initiated = FALSE;
+        break;
+    case BTIF_MEDIA_START_VS_CMD:
+        if (!btif_hf_is_call_vr_idle())
+        {
+            APPL_TRACE_IMP("ignore VS start request as Call is not idle");
+        }
+        else if (!btif_media_cb.tx_started
+             && (!btif_media_cb.tx_start_initiated || btif_media_cb.tx_enc_update_initiated))
+        {
+            btif_a2dp_encoder_update();
+            btif_media_start_vendor_command();
+        }
+        else
+        {
+            APPL_TRACE_IMP("ignore VS start request");
+        }
+        break;
+    case BTIF_MEDIA_STOP_VS_CMD:
+        if (btif_media_cb.tx_started && !btif_media_cb.tx_stop_initiated)
+            btif_media_send_vendor_stop();
+        else if((btif_media_cb.tx_start_initiated || btif_media_cb.tx_enc_update_initiated)
+                && !btif_media_cb.tx_started)
+        {
+            APPL_TRACE_IMP("Suspend Req when VSC exchange in progress,reset VSC");
+            btif_media_send_reset_vendor_state();
+        }
+        else
+            APPL_TRACE_IMP("ignore VS stop request");
+        break;
+    case BTIF_MEDIA_VS_A2DP_START_SUCCESS:
+        if (get_soc_type() == BT_SOC_SMD)
+        {
+            btif_media_cb.vs_configs_exchanged = false;
+        }
+        btif_media_cb.tx_start_initiated = FALSE;
+        btif_media_cb.tx_started = TRUE;
+        if (btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_START)
+        {
+            btif_av_reset_reconfig_flag();
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+        }
+        else
+        {
+            APPL_TRACE_ERROR("wrong cmd %d pending, ignore ACK",
+                                    btif_media_cb.a2dp_cmd_pending);
+        }
+        break;
+    case BTIF_MEDIA_VS_A2DP_START_FAILURE:
+        if (get_soc_type() == BT_SOC_SMD)
+        {
+            btif_media_cb.vs_configs_exchanged = false;
+        }
+        btif_media_cb.tx_start_initiated = FALSE;
+        if (btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_START)
+        {
+            btif_av_reset_reconfig_flag();
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+        }
+        else
+        {
+            APPL_TRACE_ERROR("wrong cmd %d pending, ignore ACK",
+                                    btif_media_cb.a2dp_cmd_pending);
+        }
+        disconnect_a2dp_on_vendor_start_failure();
+        break;
+    case BTIF_MEDIA_VS_A2DP_STOP_SUCCESS:
+        btif_media_cb.tx_started = FALSE;
+        btif_media_cb.tx_stop_initiated = FALSE;
+        if (btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_SUSPEND ||
+            btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_STOP)
+        {
+            /*Reset vendor state after stop success
+              to handle stream started for touch tone
+              to connect to second other device
+            */
+            btif_media_send_reset_vendor_state();
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+        }
+        else
+        {
+            APPL_TRACE_ERROR("wrong cmd %d pending, ignore ACK",
+                                    btif_media_cb.a2dp_cmd_pending);
+        }
+        break;
+    case BTIF_MEDIA_VS_A2DP_STOP_FAILURE:
+        btif_media_cb.tx_stop_initiated = FALSE;
+        if (btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_SUSPEND ||
+            btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_STOP)
+        {
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+        }
+        else
+        {
+            APPL_TRACE_ERROR("wrong cmd %d pending, ignore ACK",
+                                    btif_media_cb.a2dp_cmd_pending);
+        }
+        break;
+    case BTIF_MEDIA_VS_A2DP_MEDIA_CHNL_CFG_SUCCESS:
+        //btif_media_send_vendor_pref_bit_rate();
+#if (BTA_AV_CO_CP_SCMS_T == TRUE)
+        btif_media_send_vendor_scmst_hdr();
+#else
+        if (get_soc_type() == BT_SOC_SMD)
+        {
+            if (!btif_media_cb.vs_configs_exchanged &&
+                  btif_media_cb.tx_start_initiated)
+                btif_media_cb.vs_configs_exchanged = TRUE;
+            else
+            {
+                APPL_TRACE_ERROR("Dont send start,stream suspended")
+                break;
+            }
+        }
+        else
+        {
+            if (!btif_media_cb.tx_start_initiated)
+            {
+                APPL_TRACE_ERROR("Dont send start,stream suspended")
+                break;
+            }
+        }
+        btif_media_send_vendor_start();
+#endif
+        break;
+    case BTIF_MEDIA_VS_A2DP_WRITE_SBC_CFG_SUCCESS:
+        btif_media_send_vendor_media_chn_cfg();
+        break;
+    case BTIF_MEDIA_VS_A2DP_SELECTED_CODEC_SUCCESS:
+        btif_media_send_vendor_transport_cfg();
+        break;
+    case BTIF_MEDIA_VS_A2DP_TRANSPORT_CFG_SUCCESS:
+        btif_media_send_vendor_media_chn_cfg();
+        break;
+    case BTIF_MEDIA_VS_A2DP_PREF_BIT_RATE_SUCCESS:
+#if (BTA_AV_CO_CP_SCMS_T == TRUE)
+        btif_media_send_vendor_scmst_hdr();
+#else
+        if ((get_soc_type() == BT_SOC_SMD) &&
+                    (!btif_media_cb.vs_configs_exchanged))
+        {
+            btif_media_cb.vs_configs_exchanged = TRUE;
+        }
+        btif_media_send_vendor_start();
+#endif
+        break;
+#if (BTA_AV_CO_CP_SCMS_T == TRUE)
+    case BTIF_MEDIA_VS_A2DP_SET_SCMST_HDR_SUCCESS:
+        if (get_soc_type() == BT_SOC_SMD)
+        {
+            if (!btif_media_cb.vs_configs_exchanged &&
+                  btif_media_cb.tx_start_initiated)
+                btif_media_cb.vs_configs_exchanged = TRUE;
+            else
+            {
+                APPL_TRACE_ERROR("Dont send start,stream suspended")
+                break;
+            }
+        }
+        else
+        {
+            if (!btif_media_cb.tx_start_initiated)
+            {
+                APPL_TRACE_ERROR("Dont send start,stream suspended")
+                break;
+            }
+        }
+        btif_media_send_vendor_start();
+        break;
+#endif
+#endif
 #endif
     default:
         APPL_TRACE_ERROR("ERROR in %s unknown event %d", __func__, p_msg->event);
     }
     osi_free(p_msg);
-    LOG_VERBOSE(LOG_TAG, "%s: %s DONE", __func__, dump_media_event(p_msg->event));
+    APPL_TRACE_IMP("%s: %s DONE", __func__, dump_media_event(p_msg->event));
 }
 
 #if (BTA_AV_SINK_INCLUDED == TRUE)
@@ -1707,8 +2656,9 @@
 
     memcpy(p_buf, p_msg, sizeof(tBTIF_MEDIA_INIT_AUDIO));
     p_buf->hdr.event = BTIF_MEDIA_SBC_ENC_INIT;
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
     return TRUE;
 }
 
@@ -1728,8 +2678,9 @@
 
     memcpy(p_buf, p_msg, sizeof(tBTIF_MEDIA_UPDATE_AUDIO));
     p_buf->hdr.event = BTIF_MEDIA_SBC_ENC_UPDATE;
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
     return TRUE;
 }
 
@@ -1749,8 +2700,9 @@
 
     memcpy(p_buf, p_msg, sizeof(tBTIF_MEDIA_INIT_AUDIO_FEEDING));
     p_buf->hdr.event = BTIF_MEDIA_AUDIO_FEEDING_INIT;
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
     return TRUE;
 }
 
@@ -1765,11 +2717,12 @@
  *******************************************************************************/
 BOOLEAN btif_media_task_start_aa_req(void)
 {
-    BT_HDR *p_buf = osi_malloc(sizeof(BT_HDR));
+    BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
 
     p_buf->event = BTIF_MEDIA_START_AA_TX;
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
     memset(&btif_media_cb.stats, 0, sizeof(btif_media_stats_t));
     // Assign session_start_us to 1 when time_now_us() is 0 to indicate
     // btif_media_task_start_aa_req() has been called
@@ -1792,7 +2745,7 @@
  *******************************************************************************/
 BOOLEAN btif_media_task_stop_aa_req(void)
 {
-    BT_HDR *p_buf = osi_malloc(sizeof(BT_HDR));
+    BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
 
     p_buf->event = BTIF_MEDIA_STOP_AA_TX;
 
@@ -1831,10 +2784,11 @@
     if (fixed_queue_is_empty(btif_media_cb.RxSbcQ)) /*  Que is already empty */
         return TRUE;
 
-    BT_HDR *p_buf = osi_malloc(sizeof(BT_HDR));
+    BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
     p_buf->event = BTIF_MEDIA_FLUSH_AA_RX;
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
     return TRUE;
 }
 
@@ -1849,7 +2803,7 @@
  *******************************************************************************/
 BOOLEAN btif_media_task_aa_tx_flush_req(void)
 {
-    BT_HDR *p_buf = osi_malloc(sizeof(BT_HDR));
+    BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
 
     p_buf->event = BTIF_MEDIA_FLUSH_AA_TX;
 
@@ -1930,6 +2884,44 @@
 
     btif_media_cb.timestamp = 0;
 
+    if (pInitAudio->CodecType == A2D_NON_A2DP_MEDIA_CT)
+    {
+        APPL_TRACE_EVENT("%s BluetoothVendorID %x, BluetoothCodecID %d", __func__,
+                     pInitAudio->BluetoothVendorID, pInitAudio->BluetoothCodecID);
+        if ((pInitAudio->BluetoothVendorID == A2D_APTX_VENDOR_ID)
+                && (pInitAudio->BluetoothCodecID == A2D_APTX_CODEC_ID_BLUETOOTH)) {
+            btif_media_cb.aptxEncoderParams.s16SamplingFreq= pInitAudio->SamplingFreq;
+            btif_media_cb.aptxEncoderParams.s16ChannelMode = pInitAudio->ChannelMode;
+            btif_media_cb.aptxEncoderParams.u16PacketLength = 4;    // 32-bit word encoded by aptX encoder
+            btif_media_cb.TxTranscoding = BTIF_MEDIA_TRSCD_PCM_2_APTX;
+            btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_APTX_OFFSET-sizeof(BT_HDR))
+                                             < pInitAudio->MtuSize) ? (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_APTX_OFFSET
+                                                                       - sizeof(BT_HDR)) : pInitAudio->MtuSize;
+            return;
+        } else if ((pInitAudio->BluetoothVendorID == A2D_APTX_HD_VENDOR_ID)
+                && (pInitAudio->BluetoothCodecID == A2D_APTX_HD_CODEC_ID_BLUETOOTH)) {
+            btif_media_cb.aptxhdEncoderParams.s16SamplingFreq= pInitAudio->SamplingFreq;
+            btif_media_cb.aptxhdEncoderParams.s16ChannelMode = pInitAudio->ChannelMode;
+            btif_media_cb.aptxhdEncoderParams.u16PacketLength = 6;    // 48-bit word encoded by aptX encoder
+            btif_media_cb.TxTranscoding = BTIF_MEDIA_TRSCD_PCM_2_APTX_HD;
+            btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_APTX_HD_OFFSET-sizeof(BT_HDR))
+                                             < pInitAudio->MtuSize) ? (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_APTX_HD_OFFSET
+                                                                       - sizeof(BT_HDR)) : pInitAudio->MtuSize;
+            return;
+        } else {
+            /* do nothing, fall through to SBC */
+        }
+    }
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    else if (pInitAudio->CodecType == BTIF_AV_CODEC_M24) {
+        /*AAC is supported only in split mode, so only update the
+          required MTU size for AAC to send down to FW via VSC*/
+        btif_media_cb.TxAaMtuSize =  ((BTIF_MEDIA_AA_BUF_SIZE-BTIF_MEDIA_AA_AAC_OFFSET-sizeof(BT_HDR))
+            < pInitAudio->MtuSize) ? (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_AAC_OFFSET
+            - sizeof(BT_HDR)) : pInitAudio->MtuSize;
+        return;
+    }
+#endif
     /* SBC encoder config (enforced even if not used) */
     btif_media_cb.encoder.s16ChannelMode = pInitAudio->ChannelMode;
     btif_media_cb.encoder.s16NumOfSubBands = pInitAudio->NumOfSubBands;
@@ -1953,12 +2945,15 @@
             btif_media_cb.encoder.s16AllocationMethod, btif_media_cb.encoder.u16BitRate,
             btif_media_cb.encoder.s16SamplingFreq);
 
-    /* Reset entirely the SBC encoder */
-    SBC_Encoder_Init(&(btif_media_cb.encoder));
+    if (!bt_split_a2dp_enabled)
+    {
+        /* Reset entirely the SBC encoder */
+        SBC_Encoder_Init(&(btif_media_cb.encoder));
 
-    btif_media_cb.tx_sbc_frames = calculate_max_frames_per_packet();
+        btif_media_cb.tx_sbc_frames = calculate_max_frames_per_packet();
 
-    APPL_TRACE_DEBUG("%s bit pool %d", __func__, btif_media_cb.encoder.s16BitPool);
+        APPL_TRACE_DEBUG("btif_media_task_enc_init bit pool %d", btif_media_cb.encoder.s16BitPool);
+    }
 }
 
 /*******************************************************************************
@@ -1985,143 +2980,185 @@
                      pUpdateAudio->MinMtuSize, pUpdateAudio->MaxBitPool,
                      pUpdateAudio->MinBitPool);
 
-    if (!pstrEncParams->s16NumOfSubBands)
+    /* Only update the bitrate and MTU size while timer is running to make sure it has been initialized */
+    if (pUpdateAudio->CodecType == A2D_NON_A2DP_MEDIA_CT)
     {
-        APPL_TRACE_WARNING("%s SubBands are set to 0, resetting to max (%d)",
-          __func__, SBC_MAX_NUM_OF_SUBBANDS);
-        pstrEncParams->s16NumOfSubBands = SBC_MAX_NUM_OF_SUBBANDS;
+        APPL_TRACE_EVENT("%s BluetoothVendorID %x, BluetoothCodecID %d", __func__,
+                     pUpdateAudio->BluetoothVendorID, pUpdateAudio->BluetoothCodecID);
+
+        if ((pUpdateAudio->BluetoothVendorID == A2D_APTX_VENDOR_ID)
+           && (pUpdateAudio->BluetoothCodecID == A2D_APTX_CODEC_ID_BLUETOOTH)) {
+            APPL_TRACE_DEBUG("%s aptX ", __func__);
+            btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_APTX_OFFSET - sizeof(BT_HDR)) < pUpdateAudio->MinMtuSize) ?
+                                                  (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_APTX_OFFSET - sizeof(BT_HDR)) : pUpdateAudio->MinMtuSize;
+            APPL_TRACE_DEBUG("%s : aptX btif_media_cb.TxAaMtuSize %d", __func__, btif_media_cb.TxAaMtuSize);
+            enc_update_in_progress = FALSE;
+            return;
+        } else if ((pUpdateAudio->BluetoothVendorID == A2D_APTX_HD_VENDOR_ID)
+            && (pUpdateAudio->BluetoothCodecID == A2D_APTX_HD_CODEC_ID_BLUETOOTH)) {
+            APPL_TRACE_DEBUG("%s aptX HD", __func__);
+            btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_APTX_HD_OFFSET - sizeof(BT_HDR)) < pUpdateAudio->MinMtuSize) ?
+                                                  (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_APTX_HD_OFFSET - sizeof(BT_HDR)) : pUpdateAudio->MinMtuSize;
+            enc_update_in_progress = FALSE;
+            return;
+        } else {
+            /* do nothing, fall through to SBC */
+        }
     }
-
-    if (!pstrEncParams->s16NumOfBlocks)
-    {
-        APPL_TRACE_WARNING("%s Blocks are set to 0, resetting to max (%d)",
-          __func__, SBC_MAX_NUM_OF_BLOCKS);
-        pstrEncParams->s16NumOfBlocks = SBC_MAX_NUM_OF_BLOCKS;
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+    else if (pUpdateAudio->CodecType == BTIF_AV_CODEC_M24) {
+       APPL_TRACE_EVENT("%s AAC" , __func__);
+       btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE -
+                                      BTIF_MEDIA_AA_AAC_OFFSET - sizeof(BT_HDR))
+                < pUpdateAudio->MinMtuSize) ? (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_AAC_OFFSET
+                - sizeof(BT_HDR)) : pUpdateAudio->MinMtuSize;
+       enc_update_in_progress = FALSE;
+       return;
     }
-
-    if (!pstrEncParams->s16NumOfChannels)
-    {
-        APPL_TRACE_WARNING("%s Channels are set to 0, resetting to max (%d)",
-          __func__, SBC_MAX_NUM_OF_CHANNELS);
-        pstrEncParams->s16NumOfChannels = SBC_MAX_NUM_OF_CHANNELS;
-    }
-
-    btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE -
-                                  BTIF_MEDIA_AA_SBC_OFFSET - sizeof(BT_HDR))
-            < pUpdateAudio->MinMtuSize) ? (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_SBC_OFFSET
-            - sizeof(BT_HDR)) : pUpdateAudio->MinMtuSize;
-
-    /* Set the initial target bit rate */
-    pstrEncParams->u16BitRate = btif_media_task_get_sbc_rate();
-
-    if (pstrEncParams->s16SamplingFreq == SBC_sf16000)
-        s16SamplingFreq = 16000;
-    else if (pstrEncParams->s16SamplingFreq == SBC_sf32000)
-        s16SamplingFreq = 32000;
-    else if (pstrEncParams->s16SamplingFreq == SBC_sf44100)
-        s16SamplingFreq = 44100;
+#endif
     else
-        s16SamplingFreq = 48000;
-
-    do {
-        if (pstrEncParams->s16NumOfBlocks == 0 ||
-            pstrEncParams->s16NumOfSubBands == 0 ||
-            pstrEncParams->s16NumOfChannels == 0) {
-            APPL_TRACE_ERROR("%s - Avoiding division by zero...", __func__);
-            APPL_TRACE_ERROR("%s - block=%d, subBands=%d, channels=%d",
-                             __func__,
-                             pstrEncParams->s16NumOfBlocks,
-                             pstrEncParams->s16NumOfSubBands,
-                             pstrEncParams->s16NumOfChannels);
-            break;
+    {
+        if (!pstrEncParams->s16NumOfSubBands)
+        {
+            APPL_TRACE_WARNING("%s SubBands are set to 0, resetting to max (%d)",
+              __func__, SBC_MAX_NUM_OF_SUBBANDS);
+            pstrEncParams->s16NumOfSubBands = SBC_MAX_NUM_OF_SUBBANDS;
         }
 
-        if ((pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) ||
-            (pstrEncParams->s16ChannelMode == SBC_STEREO)) {
-            s16BitPool = (SINT16)((pstrEncParams->u16BitRate *
-                    pstrEncParams->s16NumOfSubBands * 1000 / s16SamplingFreq)
-                    - ((32 + (4 * pstrEncParams->s16NumOfSubBands *
-                    pstrEncParams->s16NumOfChannels)
-                    + ((pstrEncParams->s16ChannelMode - 2) *
-                    pstrEncParams->s16NumOfSubBands))
-                    / pstrEncParams->s16NumOfBlocks));
-
-            s16FrameLen = 4 + (4*pstrEncParams->s16NumOfSubBands *
-                    pstrEncParams->s16NumOfChannels) / 8
-                    + (((pstrEncParams->s16ChannelMode - 2) *
-                    pstrEncParams->s16NumOfSubBands)
-                    + (pstrEncParams->s16NumOfBlocks * s16BitPool)) / 8;
-
-            s16BitRate = (8 * s16FrameLen * s16SamplingFreq)
-                    / (pstrEncParams->s16NumOfSubBands *
-                    pstrEncParams->s16NumOfBlocks * 1000);
-
-            if (s16BitRate > pstrEncParams->u16BitRate)
-                s16BitPool--;
-
-            if (pstrEncParams->s16NumOfSubBands == 8)
-                s16BitPool = (s16BitPool > 255) ? 255 : s16BitPool;
-            else
-                s16BitPool = (s16BitPool > 128) ? 128 : s16BitPool;
-        } else {
-            s16BitPool = (SINT16)(((pstrEncParams->s16NumOfSubBands *
-                    pstrEncParams->u16BitRate * 1000)
-                    / (s16SamplingFreq * pstrEncParams->s16NumOfChannels))
-                    - (((32 / pstrEncParams->s16NumOfChannels) +
-                    (4 * pstrEncParams->s16NumOfSubBands))
-                    / pstrEncParams->s16NumOfBlocks));
-
-            pstrEncParams->s16BitPool =
-                (s16BitPool > (16 * pstrEncParams->s16NumOfSubBands)) ?
-                        (16 * pstrEncParams->s16NumOfSubBands) : s16BitPool;
+        if (!pstrEncParams->s16NumOfBlocks)
+        {
+            APPL_TRACE_WARNING("%s Blocks are set to 0, resetting to max (%d)",
+              __func__, SBC_MAX_NUM_OF_BLOCKS);
+            pstrEncParams->s16NumOfBlocks = SBC_MAX_NUM_OF_BLOCKS;
         }
 
-        if (s16BitPool < 0)
-            s16BitPool = 0;
-
-        APPL_TRACE_EVENT("%s bitpool candidate : %d (%d kbps)", __func__,
-                         s16BitPool, pstrEncParams->u16BitRate);
-
-        if (s16BitPool > pUpdateAudio->MaxBitPool) {
-            APPL_TRACE_DEBUG("%s computed bitpool too large (%d)", __func__,
-                             s16BitPool);
-            /* Decrease bitrate */
-            btif_media_cb.encoder.u16BitRate -= BTIF_MEDIA_BITRATE_STEP;
-            /* Record that we have decreased the bitrate */
-            protect |= 1;
-        } else if (s16BitPool < pUpdateAudio->MinBitPool) {
-            APPL_TRACE_WARNING("%s computed bitpool too small (%d)", __func__,
-                               s16BitPool);
-
-            /* Increase bitrate */
-            UINT16 previous_u16BitRate = btif_media_cb.encoder.u16BitRate;
-            btif_media_cb.encoder.u16BitRate += BTIF_MEDIA_BITRATE_STEP;
-            /* Record that we have increased the bitrate */
-            protect |= 2;
-            /* Check over-flow */
-            if (btif_media_cb.encoder.u16BitRate < previous_u16BitRate)
-                protect |= 3;
-        } else {
-            break;
+        if (!pstrEncParams->s16NumOfChannels)
+        {
+            APPL_TRACE_WARNING("%s Channels are set to 0, resetting to max (%d)",
+              __func__, SBC_MAX_NUM_OF_CHANNELS);
+            pstrEncParams->s16NumOfChannels = SBC_MAX_NUM_OF_CHANNELS;
         }
-        /* In case we have already increased and decreased the bitrate, just stop */
-        if (protect == 3) {
-            APPL_TRACE_ERROR("%s could not find bitpool in range", __func__);
-            break;
+
+        btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE -
+                                      BTIF_MEDIA_AA_SBC_OFFSET - sizeof(BT_HDR))
+                < pUpdateAudio->MinMtuSize) ? (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_SBC_OFFSET
+                - sizeof(BT_HDR)) : pUpdateAudio->MinMtuSize;
+
+        /* Set the initial target bit rate */
+        pstrEncParams->u16BitRate = btif_media_task_get_sbc_rate();
+
+        if (pstrEncParams->s16SamplingFreq == SBC_sf16000)
+            s16SamplingFreq = 16000;
+        else if (pstrEncParams->s16SamplingFreq == SBC_sf32000)
+            s16SamplingFreq = 32000;
+        else if (pstrEncParams->s16SamplingFreq == SBC_sf44100)
+            s16SamplingFreq = 44100;
+        else
+            s16SamplingFreq = 48000;
+
+        do {
+            if (pstrEncParams->s16NumOfBlocks == 0 ||
+                pstrEncParams->s16NumOfSubBands == 0 ||
+                pstrEncParams->s16NumOfChannels == 0) {
+                APPL_TRACE_ERROR("%s - Avoiding division by zero...", __func__);
+                APPL_TRACE_ERROR("%s - block=%d, subBands=%d, channels=%d",
+                                 __func__,
+                                 pstrEncParams->s16NumOfBlocks,
+                                 pstrEncParams->s16NumOfSubBands,
+                                 pstrEncParams->s16NumOfChannels);
+                break;
+            }
+
+            if ((pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) ||
+                (pstrEncParams->s16ChannelMode == SBC_STEREO)) {
+                s16BitPool = (SINT16)((pstrEncParams->u16BitRate *
+                        pstrEncParams->s16NumOfSubBands * 1000 / s16SamplingFreq)
+                        - ((32 + (4 * pstrEncParams->s16NumOfSubBands *
+                        pstrEncParams->s16NumOfChannels)
+                        + ((pstrEncParams->s16ChannelMode - 2) *
+                        pstrEncParams->s16NumOfSubBands))
+                        / pstrEncParams->s16NumOfBlocks));
+
+                s16FrameLen = 4 + (4*pstrEncParams->s16NumOfSubBands *
+                        pstrEncParams->s16NumOfChannels) / 8
+                        + (((pstrEncParams->s16ChannelMode - 2) *
+                        pstrEncParams->s16NumOfSubBands)
+                        + (pstrEncParams->s16NumOfBlocks * s16BitPool)) / 8;
+
+                s16BitRate = (8 * s16FrameLen * s16SamplingFreq)
+                        / (pstrEncParams->s16NumOfSubBands *
+                        pstrEncParams->s16NumOfBlocks * 1000);
+
+                if (s16BitRate > pstrEncParams->u16BitRate)
+                    s16BitPool--;
+
+                if (pstrEncParams->s16NumOfSubBands == 8)
+                    s16BitPool = (s16BitPool > 255) ? 255 : s16BitPool;
+                else
+                    s16BitPool = (s16BitPool > 128) ? 128 : s16BitPool;
+            } else {
+                s16BitPool = (SINT16)(((pstrEncParams->s16NumOfSubBands *
+                        pstrEncParams->u16BitRate * 1000)
+                        / (s16SamplingFreq * pstrEncParams->s16NumOfChannels))
+                        - (((32 / pstrEncParams->s16NumOfChannels) +
+                        (4 * pstrEncParams->s16NumOfSubBands))
+                        / pstrEncParams->s16NumOfBlocks));
+
+                pstrEncParams->s16BitPool =
+                    (s16BitPool > (16 * pstrEncParams->s16NumOfSubBands)) ?
+                            (16 * pstrEncParams->s16NumOfSubBands) : s16BitPool;
+            }
+
+            if (s16BitPool < 0)
+                s16BitPool = 0;
+
+            APPL_TRACE_EVENT("%s bitpool candidate : %d (%d kbps)", __func__,
+                             s16BitPool, pstrEncParams->u16BitRate);
+
+            if (s16BitPool > pUpdateAudio->MaxBitPool) {
+                APPL_TRACE_DEBUG("%s computed bitpool too large (%d)", __func__,
+                                 s16BitPool);
+                /* Decrease bitrate */
+                btif_media_cb.encoder.u16BitRate -= BTIF_MEDIA_BITRATE_STEP;
+                /* Record that we have decreased the bitrate */
+                protect |= 1;
+            } else if (s16BitPool < pUpdateAudio->MinBitPool) {
+                APPL_TRACE_WARNING("%s computed bitpool too small (%d)", __func__,
+                                   s16BitPool);
+
+                /* Increase bitrate */
+                UINT16 previous_u16BitRate = btif_media_cb.encoder.u16BitRate;
+                btif_media_cb.encoder.u16BitRate += BTIF_MEDIA_BITRATE_STEP;
+                /* Record that we have increased the bitrate */
+                protect |= 2;
+                /* Check over-flow */
+                if (btif_media_cb.encoder.u16BitRate < previous_u16BitRate)
+                    protect |= 3;
+            } else {
+                break;
+            }
+            /* In case we have already increased and decreased the bitrate, just stop */
+            if (protect == 3) {
+                APPL_TRACE_ERROR("%s could not find bitpool in range", __func__);
+                break;
+            }
+        } while (1);
+
+        /* Finally update the bitpool in the encoder structure */
+        pstrEncParams->s16BitPool = s16BitPool;
+
+        APPL_TRACE_DEBUG("%s final bit rate %d, final bit pool %d", __func__,
+                         btif_media_cb.encoder.u16BitRate,
+                         btif_media_cb.encoder.s16BitPool);
+
+        if (!bt_split_a2dp_enabled)
+        {
+            /* make sure we reinitialize encoder with new settings */
+            SBC_Encoder_Init(&(btif_media_cb.encoder));
         }
-    } while (1);
-
-    /* Finally update the bitpool in the encoder structure */
-    pstrEncParams->s16BitPool = s16BitPool;
-
-    APPL_TRACE_DEBUG("%s final bit rate %d, final bit pool %d", __func__,
-                     btif_media_cb.encoder.u16BitRate,
-                     btif_media_cb.encoder.s16BitPool);
-
-    /* make sure we reinitialize encoder with new settings */
-    SBC_Encoder_Init(&(btif_media_cb.encoder));
-
-    btif_media_cb.tx_sbc_frames = calculate_max_frames_per_packet();
+        btif_media_cb.tx_sbc_frames = calculate_max_frames_per_packet();
+    }
+    enc_update_in_progress = FALSE;
 }
 
 /*******************************************************************************
@@ -2194,8 +3231,8 @@
                 btif_media_cb.encoder.s16NumOfSubBands, btif_media_cb.encoder.s16NumOfBlocks,
                 btif_media_cb.encoder.s16AllocationMethod, btif_media_cb.encoder.u16BitRate,
                 btif_media_cb.encoder.s16SamplingFreq);
-
-        SBC_Encoder_Init(&(btif_media_cb.encoder));
+        if (!bt_split_a2dp_enabled)
+            SBC_Encoder_Init(&(btif_media_cb.encoder));
     }
     else
     {
@@ -2203,6 +3240,152 @@
     }
 }
 
+/*******************************************************************************
+ **
+ ** Function         btif_media_task_pcm2aptx_hd_init
+ **
+ ** Description      Init encoding task for PCM to aptX according to feeding
+ **
+ ** Returns          void
+ **
+ *******************************************************************************/
+static void btif_media_task_pcm2aptx_hd_init(tBTIF_MEDIA_INIT_AUDIO_FEEDING * p_feeding)
+{
+    BOOLEAN reconfig_needed = FALSE;
+
+    APPL_TRACE_DEBUG("%s aptX HD", __func__);
+    APPL_TRACE_DEBUG("%s PCM feeding:", __func__);
+    APPL_TRACE_DEBUG("%s sampling_freq:%d", __func__, p_feeding->feeding.cfg.pcm.sampling_freq);
+    APPL_TRACE_DEBUG("%s num_channel:%d", __func__, p_feeding->feeding.cfg.pcm.num_channel);
+    APPL_TRACE_DEBUG("%s bit_per_sample:%d", __func__, p_feeding->feeding.cfg.pcm.bit_per_sample);
+
+    /* Check the PCM feeding sampling_freq */
+    switch (p_feeding->feeding.cfg.pcm.sampling_freq)
+    {
+        case  8000:
+        case 12000:
+        case 16000:
+        case 24000:
+        case 32000:
+        case 48000:
+            /* For these sampling_freq the AV connection must be 48000 */
+            if (btif_media_cb.aptxhdEncoderParams.s16SamplingFreq != A2D_APTX_HD_SAMPLERATE_48000)
+            {
+                /* Reconfiguration needed at 48000 */
+                APPL_TRACE_DEBUG("%s Reconfiguration needed at 48000", __func__);
+                btif_media_cb.aptxhdEncoderParams.s16SamplingFreq = A2D_APTX_HD_SAMPLERATE_48000;
+                reconfig_needed = TRUE;
+            }
+            break;
+
+        case 11025:
+        case 22050:
+        case 44100:
+            /* For these sampling_freq the AV connection must be 44100 */
+            if (btif_media_cb.aptxhdEncoderParams.s16SamplingFreq != A2D_APTX_HD_SAMPLERATE_44100)
+            {
+                /* Reconfiguration needed at 44100 */
+                APPL_TRACE_DEBUG("%s Reconfiguration needed at 44100", __func__);
+                btif_media_cb.aptxhdEncoderParams.s16SamplingFreq = A2D_APTX_HD_SAMPLERATE_44100;
+                reconfig_needed = TRUE;
+            }
+            break;
+        default:
+            APPL_TRACE_DEBUG("%s Feeding PCM sampling_freq unsupported", __func__);
+            break;
+    }
+
+    /* Some AV Headsets do not support Mono => always ask for Stereo */
+    if (btif_media_cb.aptxhdEncoderParams.s16ChannelMode ==  A2D_APTX_HD_CHANNELS_MONO)
+    {
+        APPL_TRACE_DEBUG("%s Reconfiguration needed in Stereo", __func__);
+        btif_media_cb.aptxhdEncoderParams.s16ChannelMode = A2D_APTX_HD_CHANNELS_STEREO;
+        reconfig_needed = TRUE;
+    }
+
+    if (reconfig_needed != FALSE)
+    {
+        APPL_TRACE_DEBUG("%s calls APTX_HD_Encoder_Init", __func__);
+        APPL_TRACE_DEBUG("%s mtu %d", __func__, btif_media_cb.TxAaMtuSize);
+        APPL_TRACE_DEBUG("%s ch mode %d, Smp freq %d", __func__,
+                          btif_media_cb.aptxhdEncoderParams.s16ChannelMode, btif_media_cb.aptxhdEncoderParams.s16SamplingFreq);
+    } else {
+        APPL_TRACE_DEBUG("%s No aptX HD reconfig needed", __func__);
+    }
+}
+
+/*******************************************************************************
+ **
+ ** Function         btif_media_task_pcm2aptx_init
+ **
+ ** Description      Init encoding task for PCM to aptX according to feeding
+ **
+ ** Returns          void
+ **
+ *******************************************************************************/
+static void btif_media_task_pcm2aptx_init(tBTIF_MEDIA_INIT_AUDIO_FEEDING * p_feeding)
+{
+    BOOLEAN reconfig_needed = FALSE;
+
+    APPL_TRACE_DEBUG("%s PCM feeding:", __func__);
+    APPL_TRACE_DEBUG("%s sampling_freq:%d", __func__, p_feeding->feeding.cfg.pcm.sampling_freq);
+    APPL_TRACE_DEBUG("%s num_channel:%d", __func__, p_feeding->feeding.cfg.pcm.num_channel);
+    APPL_TRACE_DEBUG("%s bit_per_sample:%d", __func__, p_feeding->feeding.cfg.pcm.bit_per_sample);
+
+    /* Check the PCM feeding sampling_freq */
+    switch (p_feeding->feeding.cfg.pcm.sampling_freq)
+    {
+        case  8000:
+        case 12000:
+        case 16000:
+        case 24000:
+        case 32000:
+        case 48000:
+            /* For these sampling_freq the AV connection must be 48000 */
+            if (btif_media_cb.aptxEncoderParams.s16SamplingFreq != A2D_APTX_SAMPLERATE_48000)
+            {
+                /* Reconfiguration needed at 48000 */
+                APPL_TRACE_DEBUG("%s Reconfiguration needed at 48000", __func__);
+                btif_media_cb.aptxEncoderParams.s16SamplingFreq = A2D_APTX_SAMPLERATE_48000;
+                reconfig_needed = TRUE;
+            }
+            break;
+
+        case 11025:
+        case 22050:
+        case 44100:
+            /* For these sampling_freq the AV connection must be 44100 */
+            if (btif_media_cb.aptxEncoderParams.s16SamplingFreq != A2D_APTX_SAMPLERATE_44100)
+            {
+                /* Reconfiguration needed at 44100 */
+                APPL_TRACE_DEBUG("%s Reconfiguration needed at 44100", __func__);
+                btif_media_cb.aptxEncoderParams.s16SamplingFreq = A2D_APTX_SAMPLERATE_44100;
+                reconfig_needed = TRUE;
+            }
+            break;
+        default:
+            APPL_TRACE_DEBUG("%s Feeding PCM sampling_freq unsupported", __func__);
+            break;
+        }
+
+    /* Some AV Headsets do not support Mono => always ask for Stereo */
+    if (btif_media_cb.aptxEncoderParams.s16ChannelMode ==  A2D_APTX_CHANNELS_MONO)
+    {
+        APPL_TRACE_DEBUG("%s Reconfiguration needed in Stereo", __func__);
+        btif_media_cb.aptxEncoderParams.s16ChannelMode = A2D_APTX_CHANNELS_STEREO;
+        reconfig_needed = TRUE;
+    }
+
+    if (reconfig_needed != FALSE)
+    {
+        APPL_TRACE_DEBUG("%s calls APTX_Encoder_Init", __func__);
+        APPL_TRACE_DEBUG("%s mtu %d", __func__, btif_media_cb.TxAaMtuSize);
+        APPL_TRACE_DEBUG("%s ch mode %d, Smp freq %d", __func__,
+                          btif_media_cb.aptxEncoderParams.s16ChannelMode, btif_media_cb.aptxEncoderParams.s16SamplingFreq);
+    } else {
+        APPL_TRACE_DEBUG("%s no aptX reconfig needed", __func__);
+  }
+}
 
 /*******************************************************************************
  **
@@ -2216,7 +3399,7 @@
 static void btif_media_task_audio_feeding_init(BT_HDR *p_msg)
 {
     tBTIF_MEDIA_INIT_AUDIO_FEEDING *p_feeding = (tBTIF_MEDIA_INIT_AUDIO_FEEDING *) p_msg;
-
+    tA2D_APTX_CIE* codecInfo = 0;
     APPL_TRACE_DEBUG("btif_media_task_audio_feeding_init format:%d", p_feeding->feeding.format);
 
     /* Save Media Feeding information */
@@ -2227,10 +3410,40 @@
     switch (p_feeding->feeding.format)
     {
         case BTIF_AV_CODEC_PCM:
+        {
+            UINT8 codectype;
+            codectype = bta_av_co_get_current_codec();
+
+            if (A2D_NON_A2DP_MEDIA_CT == codectype) {
+                UINT8* ptr = bta_av_co_get_current_codecInfo();
+                if (ptr) {
+                    // tA2D_APTX_CIE starts on 4th byte
+                    codecInfo = (tA2D_APTX_CIE*) &ptr[BTA_AV_CFG_START_IDX];
+                    if (codecInfo) {
+                        APPL_TRACE_DEBUG("%s codecId = %d ", __func__, codecInfo->codecId);
+                        APPL_TRACE_DEBUG("%s vendorId = %x ", __func__, codecInfo->vendorId);
+                    }
+
+                    if (codecInfo && codecInfo->vendorId == A2D_APTX_VENDOR_ID && codecInfo->codecId == A2D_APTX_CODEC_ID_BLUETOOTH) {
+                        APPL_TRACE_DEBUG("%s aptX", __func__);
+                        btif_media_cb.TxTranscoding = BTIF_MEDIA_TRSCD_PCM_2_APTX;
+                        btif_media_task_pcm2aptx_init(p_feeding);
+                        break;
+                    } else if (codecInfo && codecInfo->vendorId == A2D_APTX_HD_VENDOR_ID && codecInfo->codecId == A2D_APTX_HD_CODEC_ID_BLUETOOTH) {
+                        APPL_TRACE_DEBUG("%s aptX HD", __func__);
+                        btif_media_cb.TxTranscoding = BTIF_MEDIA_TRSCD_PCM_2_APTX_HD;
+                        btif_media_task_pcm2aptx_hd_init(p_feeding);
+                        break;
+                    } else {
+                        /* do nothing, fall through to SBC */
+                    }
+                }
+            }
+
             btif_media_cb.TxTranscoding = BTIF_MEDIA_TRSCD_PCM_2_SBC;
             btif_media_task_pcm2sbc_init(p_feeding);
             break;
-
+        }
         default :
             APPL_TRACE_ERROR("unknown feeding format %d", p_feeding->feeding.format);
             break;
@@ -2517,6 +3730,78 @@
   thread_post(worker_thread, btif_media_task_aa_handle_timer, NULL);
 }
 
+int btif_media_task_cb_packet_send(uint8_t* packet, int length, int pcm_bytes_encoded)
+{
+    int bytes_per_frame = 2;
+    uint64_t timestamp_us = 0;
+    UINT8 codectype;
+    codectype = bta_av_co_get_current_codec();
+
+    if (btif_media_task_get_aptX_codec_type() == APTX_HD_CODEC) {
+        bytes_per_frame = 3;
+    }
+
+    if (length > 0 ) {
+
+        if (fixed_queue_length(btif_media_cb.TxAaQ) >= (MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ))
+        {
+            APPL_TRACE_WARNING("%s() - TX queue buffer count %d/%d", __func__,
+                               fixed_queue_length(btif_media_cb.TxAaQ),
+                               MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ);
+            btif_media_cb.stats.tx_queue_dropouts++;
+            timestamp_us = time_now_us();
+            btif_media_cb.stats.tx_queue_last_dropouts_us = timestamp_us;
+        }
+
+        while (fixed_queue_length(btif_media_cb.TxAaQ) >= MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ) {
+            btif_media_cb.stats.tx_queue_total_dropped_messages++;
+            osi_free(fixed_queue_try_dequeue(btif_media_cb.TxAaQ));
+        }
+
+        BT_HDR *p_buf = (BT_HDR *)osi_malloc(BTIF_MEDIA_AA_BUF_SIZE);
+
+        int rtpTimestamp = (pcm_bytes_encoded / btif_media_cb.media_feeding.cfg.pcm.num_channel / bytes_per_frame);
+
+        *((UINT32 *) (p_buf + 1)) = btif_media_cb.timestamp;
+        btif_media_cb.timestamp += rtpTimestamp;
+
+        p_buf->offset = btif_media_cb.offset;
+        p_buf->layer_specific = 0;
+
+        UINT8* ptr = (UINT8*)(p_buf + 1);
+        ptr += p_buf->offset;
+
+        memcpy(ptr, packet, length);
+        p_buf->len = length;
+
+        if (btif_media_cb.tx_flush)
+        {
+            APPL_TRACE_DEBUG("### tx suspended, discarded frame ###");
+
+            btif_media_cb.stats.tx_queue_total_flushed_messages +=
+                fixed_queue_length(btif_media_cb.TxAaQ);
+            btif_media_cb.stats.tx_queue_last_flushed_us =
+                timestamp_us;
+            btif_media_flush_q(btif_media_cb.TxAaQ);
+
+            osi_free(p_buf);
+        } else {
+            update_scheduling_stats(&btif_media_cb.stats.tx_queue_enqueue_stats,
+                                    timestamp_us,
+                                    BTIF_SINK_MEDIA_TIME_TICK_MS * 1000);
+
+            const int BYTES_PER_FRAME = 4;
+            UINT32 frames = pcm_bytes_encoded / BYTES_PER_FRAME;
+            btif_media_cb.stats.tx_queue_total_frames += frames;
+            if (frames > btif_media_cb.stats.tx_queue_max_frames_per_packet)
+                btif_media_cb.stats.tx_queue_max_frames_per_packet = frames;
+            fixed_queue_enqueue(btif_media_cb.TxAaQ, p_buf);
+        }
+
+        bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO);
+  }
+  return length;
+}
 /*******************************************************************************
  **
  ** Function         btif_media_task_aa_start_tx
@@ -2528,26 +3813,58 @@
  *******************************************************************************/
 static void btif_media_task_aa_start_tx(void)
 {
-    APPL_TRACE_DEBUG("%s media_alarm %srunning, feeding mode %d", __func__,
-                     alarm_is_scheduled(btif_media_cb.media_alarm)? "" : "not ",
-                     btif_media_cb.feeding_mode);
+    APPL_TRACE_IMP("%s media_alarm %srunning, feeding mode %d", __func__,
+    alarm_is_scheduled(btif_media_cb.media_alarm)? "" : "not ",
+    btif_media_cb.feeding_mode);
 
     last_frame_us = 0;
 
     /* Reset the media feeding state */
     btif_media_task_feeding_state_reset();
 
-    APPL_TRACE_EVENT("starting timer %dms", BTIF_MEDIA_TIME_TICK);
+    if (!bt_split_a2dp_enabled)
+    {
+        if (isA2dAptXEnabled && btif_media_task_is_aptx_configured()) {
 
-    alarm_free(btif_media_cb.media_alarm);
-    btif_media_cb.media_alarm = alarm_new_periodic("btif.media_task");
-    if (!btif_media_cb.media_alarm) {
-      LOG_ERROR(LOG_TAG, "%s unable to allocate media alarm.", __func__);
-      return;
+#if (BTA_AV_CO_CP_SCMS_T == TRUE)
+        BOOLEAN use_SCMS_T = true;
+#else
+        BOOLEAN use_SCMS_T = false;
+#endif
+        A2D_AptXCodecType aptX_codec_type = btif_media_task_get_aptX_codec_type();
+        BOOLEAN is_24bit_audio = true;
+
+        BOOLEAN test = false;
+        BOOLEAN trace = false;
+
+        A2D_start_aptX(btif_media_cb.aptxEncoderParams.encoder,
+                 aptX_codec_type,
+                 use_SCMS_T,
+                 is_24bit_audio,
+                 btif_media_cb.media_feeding.cfg.pcm.sampling_freq,
+                 btif_media_cb.media_feeding.cfg.pcm.bit_per_sample,
+                 UIPC_CH_ID_AV_AUDIO,
+                 btif_media_cb.TxAaMtuSize,
+                 UIPC_Read,
+                 btif_media_task_cb_packet_send,
+                 raise_priority_a2dp,
+                 test,
+                 trace);
+
+        } else {
+            APPL_TRACE_EVENT("starting timer %dms", BTIF_MEDIA_TIME_TICK);
+
+            alarm_free(btif_media_cb.media_alarm);
+            btif_media_cb.media_alarm = alarm_new_periodic("btif.media_task");
+            if (!btif_media_cb.media_alarm) {
+              LOG_ERROR(LOG_TAG, "%s unable to allocate media alarm.", __func__);
+              return;
+            }
+
+            alarm_set(btif_media_cb.media_alarm, BTIF_MEDIA_TIME_TICK,
+                      btif_media_task_alarm_cb, NULL);
+        }
     }
-
-    alarm_set(btif_media_cb.media_alarm, BTIF_MEDIA_TIME_TICK,
-              btif_media_task_alarm_cb, NULL);
 }
 
 /*******************************************************************************
@@ -2561,16 +3878,25 @@
  *******************************************************************************/
 static void btif_media_task_aa_stop_tx(void)
 {
-    APPL_TRACE_DEBUG("%s media_alarm is %srunning", __func__,
-                     alarm_is_scheduled(btif_media_cb.media_alarm)? "" : "not ");
+    if (!bt_split_a2dp_enabled)
+    {
+        APPL_TRACE_IMP("%s media_alarm is %srunning", __func__,
+                         alarm_is_scheduled(btif_media_cb.media_alarm)? "" : "not ");
+        const bool send_ack = alarm_is_scheduled(btif_media_cb.media_alarm) |
+                                             btif_is_remote_start_timer_scheduled();
 
-    const bool send_ack = alarm_is_scheduled(btif_media_cb.media_alarm);
+        if (isA2dAptXEnabled && A2d_aptx_thread)
+        {
+            A2D_stop_aptX();
+        }
+        else
+        {
+           /* Stop the timer first */
+           alarm_free(btif_media_cb.media_alarm);
+           btif_media_cb.media_alarm = NULL;
+        }
 
-    /* Stop the timer first */
-    alarm_free(btif_media_cb.media_alarm);
-    btif_media_cb.media_alarm = NULL;
-
-    UIPC_Close(UIPC_CH_ID_AV_AUDIO);
+        UIPC_Close(UIPC_CH_ID_AV_AUDIO);
 
     /* Try to send acknowldegment once the media stream is
        stopped. This will make sure that the A2DP HAL layer is
@@ -2583,15 +3909,47 @@
        a block/wait. Due to this acknowledgement, the A2DP HAL is guranteed
        to get the ACK for any pending command in such cases. */
 
-    if (send_ack)
-        a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+        if (send_ack)
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
 
-    /* audio engine stopped, reset tx suspended flag */
-    btif_media_cb.tx_flush = 0;
-    last_frame_us = 0;
+        /* audio engine stopped, reset tx suspended flag */
+        btif_media_cb.tx_flush = 0;
+        last_frame_us = 0;
 
-    /* Reset the media feeding state */
-    btif_media_task_feeding_state_reset();
+       /* Reset the media feeding state */
+        btif_media_task_feeding_state_reset();
+    }
+    else
+    {
+        APPL_TRACE_IMP("%s tx_started: %d, tx_stop_initiated: %d",
+            __func__, btif_media_cb.tx_started, btif_media_cb.tx_stop_initiated);
+        if (btif_media_cb.remote_start_alarm != NULL)
+        {
+            alarm_free(btif_media_cb.remote_start_alarm);
+            btif_media_cb.remote_start_alarm = NULL;
+            btif_dispatch_sm_event(BTIF_AV_RESET_REMOTE_STARTED_FLAG_EVT, NULL, 0);
+        }
+        if (btif_media_cb.tx_started && !btif_media_cb.tx_stop_initiated)
+            btif_media_send_vendor_stop();
+        else
+        {
+            if (btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_STOP ||
+                btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_SUSPEND)
+            {
+                BTIF_TRACE_DEBUG("Ack Pending Stop/Suspend");
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+            }
+            else if (btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_START)
+            {
+                BTIF_TRACE_ERROR("Ack Pending Start while Disconnect in Progress");
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS);
+            }
+            else
+            {
+                BTIF_TRACE_ERROR("Invalid cmd pending for ack");
+            }
+        }
+    }
 }
 
 static UINT32 get_frame_length()
@@ -2886,7 +4244,7 @@
 BT_HDR *btif_media_aa_readbuf(void)
 {
     uint64_t now_us = time_now_us();
-    BT_HDR *p_buf = fixed_queue_try_dequeue(btif_media_cb.TxAaQ);
+    BT_HDR *p_buf = (BT_HDR *)fixed_queue_try_dequeue(btif_media_cb.TxAaQ);
 
     btif_media_cb.stats.tx_queue_total_readbuf_calls++;
     btif_media_cb.stats.tx_queue_last_readbuf_us = now_us;
@@ -2920,15 +4278,18 @@
     UINT16 bytes_needed = blocm_x_subband * btif_media_cb.encoder.s16NumOfChannels * \
                           btif_media_cb.media_feeding.cfg.pcm.bit_per_sample / 8;
     static UINT16 up_sampled_buffer[SBC_MAX_NUM_FRAME * SBC_MAX_NUM_OF_BLOCKS
-            * SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS * 2];
+            * SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS * 4];
     static UINT16 read_buffer[SBC_MAX_NUM_FRAME * SBC_MAX_NUM_OF_BLOCKS
-            * SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS];
+            * SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS * 2];
     UINT32 src_size_used;
     UINT32 dst_size_used;
     BOOLEAN fract_needed;
     INT32   fract_max;
     INT32   fract_threshold;
     UINT32  nb_byte_read;
+    #ifdef BT_AUDIO_SYSTRACE_LOG
+    char trace_buf[512];
+    #endif
 
     /* Get the SBC sampling rate */
     switch (btif_media_cb.encoder.s16SamplingFreq)
@@ -2950,7 +4311,7 @@
     if (sbc_sampling == btif_media_cb.media_feeding.cfg.pcm.sampling_freq) {
         read_size = bytes_needed - btif_media_cb.media_feeding_state.pcm.aa_feed_residue;
         nb_byte_read = UIPC_Read(channel_id, &event,
-                  ((UINT8 *)btif_media_cb.encoder.as16PcmBuffer) +
+                  ((UINT8 *)btif_media_cb.encoder.as32PcmBuffer) +
                   btif_media_cb.media_feeding_state.pcm.aa_feed_residue,
                   read_size);
         if (nb_byte_read == read_size) {
@@ -3024,6 +4385,19 @@
         btif_media_cb.stats.media_read_total_underrun_bytes += (read_size - nb_byte_read);
         btif_media_cb.stats.media_read_total_underrun_count++;
         btif_media_cb.stats.media_read_last_underrun_us = time_now_us();
+        #ifdef BT_AUDIO_SYSTRACE_LOG
+        snprintf(trace_buf, 32, "A2DP UNDERRUN read %ld ", nb_byte_read);
+
+        if (PERF_SYSTRACE)
+        {
+            ATRACE_BEGIN(trace_buf);
+        }
+
+        if (PERF_SYSTRACE)
+        {
+            ATRACE_END();
+        }
+        #endif
 
         if (nb_byte_read == 0)
             return FALSE;
@@ -3056,7 +4430,7 @@
     if(btif_media_cb.media_feeding_state.pcm.aa_feed_residue >= bytes_needed)
     {
         /* Copy the output pcm samples in SBC encoding buffer */
-        memcpy((UINT8 *)btif_media_cb.encoder.as16PcmBuffer,
+        memcpy((UINT8 *)btif_media_cb.encoder.as32PcmBuffer,
                 (UINT8 *)up_sampled_buffer,
                 bytes_needed);
         /* update the residue */
@@ -3091,7 +4465,7 @@
                              btif_media_cb.encoder.s16NumOfBlocks;
 
     while (nb_frame) {
-        BT_HDR *p_buf = osi_malloc(BTIF_MEDIA_AA_BUF_SIZE);
+        BT_HDR *p_buf = (BT_HDR *)osi_malloc(BTIF_MEDIA_AA_BUF_SIZE);
 
         /* Init buffer */
         p_buf->offset = BTIF_MEDIA_AA_SBC_OFFSET;
@@ -3103,12 +4477,14 @@
             /* Write @ of allocated buffer in encoder.pu8Packet */
             btif_media_cb.encoder.pu8Packet = (UINT8 *) (p_buf + 1) + p_buf->offset + p_buf->len;
             /* Fill allocated buffer with 0 */
-            memset(btif_media_cb.encoder.as16PcmBuffer, 0, blocm_x_subband
-                    * btif_media_cb.encoder.s16NumOfChannels);
+            memset(btif_media_cb.encoder.as32PcmBuffer, 0, blocm_x_subband
+                               * btif_media_cb.encoder.s16NumOfChannels * 2);
 
             /* Read PCM data and upsample them if needed */
             if (btif_media_aa_read_feeding(UIPC_CH_ID_AV_AUDIO))
             {
+                size_t frames  = blocm_x_subband * btif_media_cb.encoder.s16NumOfChannels;
+                memcpy_by_audio_format(btif_media_cb.encoder.as16PcmBuffer, AUDIO_FORMAT_PCM_16_BIT, btif_media_cb.encoder.as32PcmBuffer, AUDIO_FORMAT_PCM_8_24_BIT, frames);
                 SBC_Encoder(&(btif_media_cb.encoder));
 
                 /* Update SBC frame length */
@@ -3190,7 +4566,7 @@
 static void btif_media_aa_prep_2_send(UINT8 nb_frame, uint64_t timestamp_us)
 {
     // Check for TX queue overflow
-
+    BD_ADDR peer_bda;
     if (nb_frame > MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ)
         nb_frame = MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ;
 
@@ -3214,8 +4590,8 @@
         }
 
         // Request RSSI for log purposes if we had to flush buffers
-        bt_bdaddr_t peer_bda = btif_av_get_addr();
-        BTM_ReadRSSI(peer_bda.address, btm_read_rssi_cb);
+        btif_av_get_addr(peer_bda);
+        BTM_ReadRSSI(peer_bda, btm_read_rssi_cb);
     }
 
     // Transcode frame
@@ -3248,6 +4624,11 @@
 
     btif_get_num_aa_frame_iteration(&nb_iterations, &nb_frame_2_send);
 
+    /* get the number of frame to send */
+    #ifdef BT_AUDIO_SYSTRACE_LOG
+    char trace_buf[1024];
+    #endif
+
     if (nb_frame_2_send != 0) {
         for (UINT8 counter = 0; counter < nb_iterations; counter++)
         {
@@ -3258,9 +4639,595 @@
 
     LOG_VERBOSE(LOG_TAG, "%s Sent %d frames per iteration, %d iterations",
                         __func__, nb_frame_2_send, nb_iterations);
+    #ifdef BT_AUDIO_SYSTRACE_LOG
+    snprintf(trace_buf, 32, "btif_media_send_aa_frame:");
+    if (PERF_SYSTRACE)
+    {
+        ATRACE_BEGIN(trace_buf);
+    }
+    #endif
+
+    /* send it */
+
+    #ifdef BT_AUDIO_SYSTRACE_LOG
+    if (PERF_SYSTRACE)
+    {
+        ATRACE_END();
+    }
+    #endif
     bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO);
 }
 
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+/*******************************************************************************
+ **
+ ** Function         bta_av_co_send_vendor_start
+ **
+ ** Description      Send Vendor Specific A2dp START command to controller
+ **
+ ** Returns          TRUE if command succeeds, FALSE otherwize
+ **
+ *******************************************************************************/
+
+#define HCI_VSQC_CONTROLLER_A2DP_OPCODE 0x000A
+
+#define VS_QHCI_READ_A2DP_CFG                 0x01
+#define VS_QHCI_WRITE_SBC_CFG                 0x02
+#define VS_QHCI_WRITE_A2DP_MEDIA_CHANNEL_CFG  0x03
+#define VS_QHCI_START_A2DP_MEDIA              0x04
+#define VS_QHCI_STOP_A2DP_MEDIA               0x05
+#define VS_QHCI_A2DP_WRITE_SUGGESTED_BITRATE  0x06
+#define VS_QHCI_A2DP_TRANSPORT_CONFIGURATION  0x07
+#define VS_QHCI_A2DP_WRITE_SCMS_T_CP          0x08
+#define VS_QHCI_A2DP_SELECTED_CODEC           0x09
+
+#define A2DP_CODEC_SBC      0
+#define A2DP_CODEC_AAC      2
+/* Below type is not defined in spec, it is for our convenience */
+#define A2DP_CODEC_APTX     8
+
+#define A2DP_CODEC_APTX_HD  9
+/* Need to check if we need a different type for APTX low latency
+ * or just we can handle with reducing the MTU updated in media
+ * channel configuration.
+ */
+
+#define A2DP_TRANSPORT_TYPE_SLIMBUS     0
+
+/* Better to match the codec type, for PCM we can use undefined number */
+#define A2DP_TRANSPORT_STREAM_TYPE_PCM      10
+#define A2DP_TRANSPORT_STREAM_TYPE_SBC      0
+#define A2DP_TRANSPORT_STREAM_TYPE_AAC      2
+#define A2DP_TRANSPORT_STREAM_TYPE_APTX     8
+#define A2DP_TRANSPORT_STREAM_TYPE_APTX_HD  9
+
+void disconnect_a2dp_on_vendor_start_failure()
+{
+    bt_bdaddr_t bd_addr;
+    APPL_TRACE_IMP("disconnect_a2dp_on_vendor_start_failure");
+    btif_av_reset_reconfig_flag();
+    btif_av_get_peer_addr(&bd_addr);
+    btif_dispatch_sm_event(BTIF_AV_DISCONNECT_REQ_EVT,(char*)&bd_addr,
+            sizeof(bt_bdaddr_t));
+}
+
+void btif_media_send_reset_vendor_state()
+{
+    BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
+
+    p_buf->event = BTIF_MEDIA_RESET_VS_STATE;
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+}
+
+void btif_media_start_vendor_command()
+{
+    APPL_TRACE_IMP("btif_media_start_vendor_command_exchange");
+    btif_media_cb.tx_start_initiated = TRUE;
+    btif_media_cb.tx_enc_update_initiated = FALSE;
+
+    if (get_soc_type() == BT_SOC_SMD)
+    {
+        APPL_TRACE_IMP("vs_configs_exchanged:%u", btif_media_cb.vs_configs_exchanged);
+        if(btif_media_cb.vs_configs_exchanged)
+        {
+            btif_media_send_vendor_start();
+        }
+        else
+        {
+            btif_media_send_vendor_write_sbc_cfg();
+        }
+    }
+    else
+    {
+        btif_media_send_vendor_selected_codec();
+    }
+}
+
+void btif_media_on_start_vendor_command()
+{
+    BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
+
+    p_buf->event = BTIF_MEDIA_START_VS_CMD;
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+}
+
+void btif_media_on_stop_vendor_command()
+{
+    BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
+
+    APPL_TRACE_IMP("btif_media_on_stop_vendor_command");
+    p_buf->event = BTIF_MEDIA_STOP_VS_CMD;
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+}
+
+void btif_media_a2dp_start_cb(tBTM_VSC_CMPL *param)
+{
+    unsigned char status = 0;
+    BT_HDR *p_buf;
+
+    if (param->param_len)
+    {
+        status = param->p_param_buf[0];
+    }
+    APPL_TRACE_IMP("VS_QHCI_START_A2DP_MEDIA sent with error code: %u", status);
+
+    p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
+
+    if (!status)
+        p_buf->event = BTIF_MEDIA_VS_A2DP_START_SUCCESS;
+    else
+        p_buf->event = BTIF_MEDIA_VS_A2DP_START_FAILURE;
+
+    if (btif_media_cmd_msg_queue != NULL)
+    {
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("Message queue cleaned up");
+        if (!status)
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+        else
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+        btif_av_reset_reconfig_flag();
+    }
+}
+
+BOOLEAN btif_media_send_vendor_start()
+{
+    UINT8 param[2];
+
+    APPL_TRACE_IMP("btif_media_send_vendor_start");
+
+    param[0] = VS_QHCI_START_A2DP_MEDIA;
+    param[1] = 0; /*needs to send index for multi A2dp*/
+
+    return BTA_DmVendorSpecificCommand(HCI_VSQC_CONTROLLER_A2DP_OPCODE, 2,
+                                            param, btif_media_a2dp_start_cb);
+}
+
+void btif_media_a2dp_stop_cb(tBTM_VSC_CMPL *param)
+{
+    unsigned char status = 0;
+    BT_HDR *p_buf;
+
+    if (param->param_len)
+    {
+        status = param->p_param_buf[0];
+    }
+    APPL_TRACE_IMP("VS_QHCI_STOP_A2DP_MEDIA sent with error code: %u", status);
+
+    p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
+
+    if (!status)
+        p_buf->event = BTIF_MEDIA_VS_A2DP_STOP_SUCCESS;
+    else
+        p_buf->event = BTIF_MEDIA_VS_A2DP_STOP_FAILURE;
+
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+    else
+    {
+        APPL_TRACE_ERROR("Message queue cleaned up");
+        if (!status)
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+        else
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+    }
+}
+
+BOOLEAN btif_media_send_vendor_stop()
+{
+    UINT8 param[2];
+
+    APPL_TRACE_IMP("btif_media_send_vendor_stop");
+
+    btif_media_cb.tx_stop_initiated = TRUE;
+
+    param[0] = VS_QHCI_STOP_A2DP_MEDIA;
+    param[1] = 0; /*needs to send index for multi A2dp*/
+
+    return BTA_DmVendorSpecificCommand(HCI_VSQC_CONTROLLER_A2DP_OPCODE, 2,
+                                            param, btif_media_a2dp_stop_cb);
+}
+
+void btif_media_selected_codec_cb(tBTM_VSC_CMPL *param)
+{
+    unsigned char status = 0;
+    BT_HDR *p_buf;
+
+    if (param->param_len)
+    {
+        status = param->p_param_buf[0];
+    }
+    APPL_TRACE_IMP("VS_QHCI_A2DP_SELECTED_CODEC sent with error code: %u",
+                                                                        status);
+
+    if (!status)
+    {
+        p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
+        p_buf->event = BTIF_MEDIA_VS_A2DP_SELECTED_CODEC_SUCCESS;
+        if (btif_media_cmd_msg_queue != NULL)
+            fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+        else
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("Error in processing Vendor command response");
+        a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+        disconnect_a2dp_on_vendor_start_failure();
+    }
+}
+
+BOOLEAN btif_media_send_vendor_selected_codec()
+{
+    UINT8 param[12], codec_type = A2DP_CODEC_SBC;
+    UINT16 index = 0;
+
+    codec_type = bta_av_co_get_current_codec();
+    if (codec_type == A2D_NON_A2DP_MEDIA_CT) {
+        UINT8* ptr = bta_av_co_get_current_codecInfo();
+        if (ptr) {
+            tA2D_APTX_CIE* codecInfo = (tA2D_APTX_CIE*) &ptr[BTA_AV_CFG_START_IDX];
+            if (codecInfo && codecInfo->vendorId == A2D_APTX_VENDOR_ID && codecInfo->codecId == A2D_APTX_CODEC_ID_BLUETOOTH)
+                   codec_type = A2DP_CODEC_APTX;
+            else if (codecInfo && codecInfo->vendorId == A2D_APTX_HD_VENDOR_ID && codecInfo->codecId == A2D_APTX_HD_CODEC_ID_BLUETOOTH)
+                   codec_type = A2DP_CODEC_APTX_HD;
+        }
+    }
+
+    APPL_TRACE_IMP("btif_media_send_selected_codec: codec: %d", codec_type);
+    param[index++] = VS_QHCI_A2DP_SELECTED_CODEC;
+    param[index++] = codec_type;
+    param[index++] = 0; //Max Latency
+    param[index++] = 0; //Delay report
+#if (BTA_AV_CO_CP_SCMS_T == TRUE)
+    param[index++] = bta_av_co_cp_is_active();
+#else
+    param[index++] = 0;
+#endif
+    param[index++] = bta_av_co_cp_get_flag();
+    param[index++] = (UINT8)(btif_media_cb.media_feeding.cfg.pcm.sampling_freq & 0xFF);
+    param[index++] = (UINT8)((btif_media_cb.media_feeding.cfg.pcm.sampling_freq >> 8)& 0xFF);
+    if (codec_type == A2DP_CODEC_SBC)
+    {
+        param[index++] = (UINT8)btif_media_cb.encoder.s16NumOfSubBands;
+        param[index++] = (UINT8)btif_media_cb.encoder.s16NumOfBlocks;
+    }
+    return BTA_DmVendorSpecificCommand(HCI_VSQC_CONTROLLER_A2DP_OPCODE, index,
+                                            param, btif_media_selected_codec_cb);
+}
+
+void btif_media_transport_cfg_cb(tBTM_VSC_CMPL *param)
+{
+    unsigned char status = 0;
+    BT_HDR *p_buf;
+
+    if (param->param_len)
+    {
+        status = param->p_param_buf[0];
+    }
+    APPL_TRACE_IMP("VS_QHCI_A2DP_TRANSPORT_CFG sent with error code: %u",
+                                                                        status);
+
+    if (!status)
+    {
+        p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
+        p_buf->event = BTIF_MEDIA_VS_A2DP_TRANSPORT_CFG_SUCCESS;
+        if (btif_media_cmd_msg_queue != NULL)
+            fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+        else
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("Error in processing Vendor command response");
+        a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+        disconnect_a2dp_on_vendor_start_failure();
+    }
+}
+BOOLEAN btif_media_send_vendor_transport_cfg()
+{
+    UINT8 param[3];
+    UINT8 codec_type = bta_av_co_get_current_codec();
+    UINT8 stream_type;
+    APPL_TRACE_IMP("btif_media_send_vendor_transport_cfg: codec: %d", codec_type);
+    stream_type = codec_type;
+
+    if (codec_type == A2D_NON_A2DP_MEDIA_CT) {
+        UINT8* ptr = bta_av_co_get_current_codecInfo();
+        if (ptr) {
+            tA2D_APTX_CIE* codecInfo = (tA2D_APTX_CIE*) &ptr[BTA_AV_CFG_START_IDX];
+            if (codecInfo && codecInfo->vendorId == A2D_APTX_VENDOR_ID && codecInfo->codecId == A2D_APTX_CODEC_ID_BLUETOOTH)
+                  stream_type = A2DP_TRANSPORT_STREAM_TYPE_APTX;
+            else if (codecInfo && codecInfo->vendorId == A2D_APTX_HD_VENDOR_ID && codecInfo->codecId == A2D_APTX_HD_CODEC_ID_BLUETOOTH)
+                  stream_type = A2DP_TRANSPORT_STREAM_TYPE_APTX_HD;
+        }
+    }
+
+    param[0] = VS_QHCI_A2DP_TRANSPORT_CONFIGURATION;
+    param[1] = A2DP_TRANSPORT_TYPE_SLIMBUS;
+    param[2] = stream_type;
+
+    return BTA_DmVendorSpecificCommand(HCI_VSQC_CONTROLLER_A2DP_OPCODE, 3,
+                                            param, btif_media_transport_cfg_cb);
+}
+
+void btif_media_a2dp_media_chn_cfg_cb(tBTM_VSC_CMPL *param)
+{
+    unsigned char status = 0;
+    BT_HDR *p_buf;
+
+    if (param->param_len)
+    {
+        status = param->p_param_buf[0];
+    }
+    APPL_TRACE_IMP("VS_QHCI_WRITE_A2DP_MEDIA_CHANNEL_CFG sent with error code: %u",
+                                                                        status);
+
+    if (!status)
+    {
+        p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
+        p_buf->event = BTIF_MEDIA_VS_A2DP_MEDIA_CHNL_CFG_SUCCESS;
+        if (btif_media_cmd_msg_queue != NULL)
+            fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+        else
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("Error in processing Vendor command response");
+        a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+        disconnect_a2dp_on_vendor_start_failure();
+    }
+}
+
+BOOLEAN btif_media_send_vendor_media_chn_cfg()
+{
+    UINT8 param[8];
+    bt_bdaddr_t bd_addr;
+    BD_ADDR addr;
+    UINT8 codec_type = A2DP_CODEC_SBC;
+
+    if (btif_av_is_peer_edr() && (btif_av_peer_supports_3mbps() == FALSE)) {
+        // This condition would be satisfied only if the remote device is
+        // EDR and supports only 2 Mbps, but the effective AVDTP MTU size
+        // exceeds the 2DH5 packet size.
+        APPL_TRACE_DEBUG("%s The remote devce is EDR but does not support 3 Mbps", __func__);
+
+        if (btif_media_cb.TxAaMtuSize > MAX_2MBPS_AVDTP_MTU) {
+            APPL_TRACE_WARNING("%s Restricting AVDTP MTU size to %d",
+                __func__, MAX_2MBPS_AVDTP_MTU);
+            btif_media_cb.TxAaMtuSize = MAX_2MBPS_AVDTP_MTU;
+        }
+    }
+
+    codec_type = bta_av_co_get_current_codec();
+    if (codec_type == A2D_NON_A2DP_MEDIA_CT) {
+        UINT8* ptr = bta_av_co_get_current_codecInfo();
+        if (ptr) {
+            tA2D_APTX_CIE* codecInfo = (tA2D_APTX_CIE*) &ptr[BTA_AV_CFG_START_IDX];
+            if (codecInfo && codecInfo->vendorId == A2D_APTX_VENDOR_ID && codecInfo->codecId == A2D_APTX_CODEC_ID_BLUETOOTH)
+                   codec_type = A2DP_CODEC_APTX;
+            else if (codecInfo && codecInfo->vendorId == A2D_APTX_HD_VENDOR_ID && codecInfo->codecId == A2D_APTX_HD_CODEC_ID_BLUETOOTH)
+                   codec_type = A2DP_CODEC_APTX_HD;
+        }
+    }
+
+    if ((codec_type == A2DP_CODEC_APTX) || (codec_type == A2DP_CODEC_APTX_HD))
+    {
+        if (btif_media_cb.TxAaMtuSize > MAX_2MBPS_AVDTP_MTU)
+        {
+            APPL_TRACE_IMP("Restricting AVDTP MTU size to 663 for APTx codecs");
+            btif_media_cb.TxAaMtuSize = MAX_2MBPS_AVDTP_MTU;
+        }
+    }
+
+    btif_av_get_peer_addr(&bd_addr);
+    memcpy(addr, bd_addr.address, sizeof(BD_ADDR));
+    UINT16 acl_hdl = BTM_GetHCIConnHandle(addr, BT_TRANSPORT_BR_EDR);
+    APPL_TRACE_IMP("btif_media_send_vendor_media_chn_cfg");
+    APPL_TRACE_IMP("AVDTP mtu: %u, hdl: %u", btif_media_cb.TxAaMtuSize, acl_hdl);
+
+    if ((codec_type == A2DP_CODEC_SBC) && (btif_media_cb.max_bitpool <= BTIF_A2DP_MAX_BITPOOL_MQ))
+    {
+        APPL_TRACE_IMP("Restricting streaming MTU size for MQ Bitpool");
+        btif_media_cb.TxAaMtuSize = MAX_2MBPS_AVDTP_MTU;
+    }
+
+    param[0] = VS_QHCI_WRITE_A2DP_MEDIA_CHANNEL_CFG;
+    param[1] = 0; /*needs to send index for multi A2dp*/
+    param[2] = (UINT8)(acl_hdl & 0x00ff);
+    param[3] = (UINT8)(((acl_hdl & 0xff00) >> 8) & 0x00ff);
+    param[4] = (UINT8)(btif_av_get_streaming_channel_id()& 0x00ff);
+    param[5] = (UINT8)(((btif_av_get_streaming_channel_id() & 0xff00)
+                                                       >> 8) & 0x00ff);
+    param[6] = (UINT8)(btif_media_cb.TxAaMtuSize & 0x00ff);
+    param[7] = (UINT8)(((btif_media_cb.TxAaMtuSize & 0xff00) >> 8) & 0x00ff);
+
+    return BTA_DmVendorSpecificCommand(HCI_VSQC_CONTROLLER_A2DP_OPCODE, 8,
+                                    param, btif_media_a2dp_media_chn_cfg_cb);
+}
+
+void btif_media_a2dp_write_sbc_cfg_cb(tBTM_VSC_CMPL *param)
+{
+    unsigned char status = 0;
+    BT_HDR *p_buf;
+
+    if (param->param_len)
+    {
+        status = param->p_param_buf[0];
+    }
+    APPL_TRACE_IMP("VS_QHCI_WRITE_SBC_CFG sent with error code: %u", status);
+
+    if (!status)
+    {
+        p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
+        p_buf->event = BTIF_MEDIA_VS_A2DP_WRITE_SBC_CFG_SUCCESS;
+        if (btif_media_cmd_msg_queue != NULL)
+            fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+        else
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("Error in processing Vendor command response");
+        a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+        disconnect_a2dp_on_vendor_start_failure();
+    }
+}
+
+BOOLEAN btif_media_send_vendor_write_sbc_cfg()
+{
+    UINT8 param[12];
+    bt_bdaddr_t bd_addr;
+    BD_ADDR addr;
+    btif_av_get_peer_addr(&bd_addr);
+    memcpy(addr, bd_addr.address, sizeof(BD_ADDR));
+    UINT16 acl_hdl = BTM_GetHCIConnHandle(addr, BT_TRANSPORT_BR_EDR);
+    APPL_TRACE_IMP("btif_media_send_vendor_write_sbc_cfg");
+    APPL_TRACE_IMP("acl hdl: %u", acl_hdl);
+    APPL_TRACE_IMP("channel mode: %u", btif_media_cb.encoder.s16ChannelMode);
+    APPL_TRACE_IMP("sampling frequency: %u", btif_media_cb.encoder.s16SamplingFreq);
+    APPL_TRACE_IMP("allocation method: %u", btif_media_cb.encoder.s16AllocationMethod);
+    APPL_TRACE_IMP("subbands: %u", btif_media_cb.encoder.s16NumOfSubBands);
+    APPL_TRACE_IMP("num of blocks: %u", btif_media_cb.encoder.s16NumOfBlocks);
+    APPL_TRACE_IMP("bitpool: <%u>,<%u>", btif_media_cb.min_bitpool, btif_media_cb.max_bitpool);
+    APPL_TRACE_IMP("Scmst flag: %u", bta_av_co_cp_get_flag());
+
+    param[0] = VS_QHCI_WRITE_SBC_CFG;
+    param[1] = (UINT8)((1 << (3 - btif_media_cb.encoder.s16ChannelMode)) |
+            (1 << (7 - btif_media_cb.encoder.s16SamplingFreq)));
+    param[2] = (UINT8)((1 << btif_media_cb.encoder.s16AllocationMethod) |
+            (1 << (3 - (btif_media_cb.encoder.s16NumOfSubBands >> 3))) |
+            (1 << (7 - ((btif_media_cb.encoder.s16NumOfBlocks - 4) >> 2))));
+    param[3] = btif_media_cb.min_bitpool;
+    param[4] = btif_media_cb.max_bitpool;
+    param[5] = 0; // Not in use as latency calculation will now be taken care of in SOC
+    param[6] = 0; // Not in use as latency calculation will now be taken care of in SOC
+    param[7] = 0; // Not in use as latency calculation will now be taken care of in SOC
+    param[8] = 0; // Not in use as latency calculation will now be taken care of in SOC
+    param[9] = 0; // 0 as delayed report not supported
+#if (BTA_AV_CO_CP_SCMS_T == TRUE)
+    param[10] = 1;
+#else
+    param[10] = 0;
+#endif
+    param[11] = bta_av_co_cp_get_flag();
+
+    return BTA_DmVendorSpecificCommand(HCI_VSQC_CONTROLLER_A2DP_OPCODE, 12,
+                                    param, btif_media_a2dp_write_sbc_cfg_cb);
+}
+
+void btif_media_pref_bit_rate_cb(tBTM_VSC_CMPL *param)
+{
+    unsigned char status = 0;
+    BT_HDR *p_buf;
+
+    if (param->param_len)
+    {
+        status = param->p_param_buf[0];
+    }
+    APPL_TRACE_IMP("VS_QHCI_A2DP_WRITE_SUGGESTED_BITRATE sent with error code: %u", status);
+
+    if (!status)
+    {
+        p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
+        p_buf->event = BTIF_MEDIA_VS_A2DP_PREF_BIT_RATE_SUCCESS;
+        if (btif_media_cmd_msg_queue != NULL)
+            fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+        else
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("Error in processing Vendor command response");
+        a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+        disconnect_a2dp_on_vendor_start_failure();
+    }
+}
+
+BOOLEAN btif_media_send_vendor_pref_bit_rate()
+{
+    UINT8 param[3];
+
+    APPL_TRACE_IMP("btif_media_send_vendor_pref_bit_rate: bitrate: %d", btif_media_cb.encoder.u16BitRate);
+
+    param[0] = VS_QHCI_A2DP_WRITE_SUGGESTED_BITRATE;
+    param[1] = (UINT8)(btif_media_cb.encoder.u16BitRate & 0x00ff);
+    param[2] = (UINT8)((btif_media_cb.encoder.u16BitRate & 0xff00) >> 8);
+
+    return BTA_DmVendorSpecificCommand(HCI_VSQC_CONTROLLER_A2DP_OPCODE, 3,
+                                            param, btif_media_pref_bit_rate_cb);
+}
+
+void btif_media_scmst_cb(tBTM_VSC_CMPL *param)
+{
+    unsigned char status = 0;
+    BT_HDR *p_buf;
+
+    if (param->param_len)
+    {
+        status = param->p_param_buf[0];
+    }
+    APPL_TRACE_IMP("VS_QHCI_A2DP_WRITE_SCMS_T_CP sent with error code: %u", status);
+
+    if (!status)
+    {
+        p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
+        p_buf->event = BTIF_MEDIA_VS_A2DP_SET_SCMST_HDR_SUCCESS;
+        if (btif_media_cmd_msg_queue != NULL)
+            fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+        else
+            a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("Error in processing Vendor command response");
+        a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+        disconnect_a2dp_on_vendor_start_failure();
+    }
+}
+
+BOOLEAN btif_media_send_vendor_scmst_hdr()
+{
+    UINT8 param[3];
+
+    APPL_TRACE_IMP("btif_media_send_vendor_scmst_hdr");
+
+    param[0] = VS_QHCI_A2DP_WRITE_SCMS_T_CP;
+    param[1] = bta_av_co_cp_get_flag();
+
+    return BTA_DmVendorSpecificCommand(HCI_VSQC_CONTROLLER_A2DP_OPCODE, 2,
+                                            param, btif_media_scmst_cb);
+}
+
+#endif
+
 #endif /* BTA_AV_INCLUDED == TRUE */
 
 /*******************************************************************************
diff --git a/btif/src/btif_rc.c b/btif/src/btif_rc.c
index 28a2499..1657b13 100644
--- a/btif/src/btif_rc.c
+++ b/btif/src/btif_rc.c
@@ -38,6 +38,7 @@
 #include "bta_api.h"
 #include "bta_av_api.h"
 #include "btif_av.h"
+#include "btif_media.h"
 #include "btif_common.h"
 #include "btif_util.h"
 #include "bt_common.h"
@@ -47,6 +48,7 @@
 #include "osi/include/list.h"
 #include "osi/include/properties.h"
 #include "btu.h"
+#include "stack/sdp/sdpint.h"
 #include "log/log.h"
 #define RC_INVALID_TRACK_ID (0xFFFFFFFFFFFFFFFFULL)
 
@@ -54,52 +56,139 @@
 **  Constants & Macros
 ******************************************************************************/
 
+/* Support Two RC Handles simultaneously*/
+#define BTIF_RC_NUM_CB       2
+/* Default index*/
+#define BTIF_RC_DEFAULT_INDEX 0
 /* cod value for Headsets */
 #define COD_AV_HEADSETS        0x0404
 /* for AVRC 1.4 need to change this */
 #define MAX_RC_NOTIFICATIONS AVRC_EVT_VOLUME_CHANGE
+//#define TEST_BROWSE_RESPONSE
+#define MAX_FOLDER_RSP_SUPPORT 10
 
-#define IDX_GET_PLAY_STATUS_RSP   0
-#define IDX_LIST_APP_ATTR_RSP     1
-#define IDX_LIST_APP_VALUE_RSP    2
-#define IDX_GET_CURR_APP_VAL_RSP  3
-#define IDX_SET_APP_VAL_RSP       4
-#define IDX_GET_APP_ATTR_TXT_RSP  5
-#define IDX_GET_APP_VAL_TXT_RSP   6
-#define IDX_GET_ELEMENT_ATTR_RSP  7
+#define IDX_GET_PLAY_STATUS_RSP    0
+#define IDX_LIST_APP_ATTR_RSP      1
+#define IDX_LIST_APP_VALUE_RSP     2
+#define IDX_GET_CURR_APP_VAL_RSP   3
+#define IDX_SET_APP_VAL_RSP        4
+#define IDX_GET_APP_ATTR_TXT_RSP   5
+#define IDX_GET_APP_VAL_TXT_RSP    6
+#define IDX_GET_ELEMENT_ATTR_RSP   7
+#define IDX_GET_FOLDER_ITEMS_RSP   8
+#define IDX_SET_FOLDER_ITEM_RSP    9
+#define IDX_SET_ADDRESS_PLAYER_RSP 10
+#define IDX_SET_BROWSE_PLAYER_RSP  11
+#define IDX_CHANGE_PATH_RSP        12
+#define IDX_PLAY_ITEM_RSP          13
+#define IDX_GET_ITEM_ATTR_RSP      14
+#define IDX_GET_TOTAL_ITEMS_RSP    15
 #define MAX_VOLUME 128
 #define MAX_LABEL 16
 #define MAX_TRANSACTIONS_PER_SESSION 16
-#define MAX_CMD_QUEUE_LEN 8
 #define PLAY_STATUS_PLAYING 1
+#define MAX_CMD_QUEUE_LEN 16
+#define ERR_PLAYER_NOT_ADDRESED 0x13
+#define BTRC_FEAT_AVRC_UI_UPDATE 0x08
+
+#if (defined(AVCT_COVER_ART_INCLUDED) && (AVCT_COVER_ART_INCLUDED == TRUE))
+#define MAX_ELEM_ATTR_SIZE 8
+#else
+#define MAX_ELEM_ATTR_SIZE 7
+#endif
 
 #define CHECK_RC_CONNECTED                                                                  \
     BTIF_TRACE_DEBUG("## %s ##", __FUNCTION__);                                            \
-    if (btif_rc_cb.rc_connected == FALSE)                                                    \
-    {                                                                                       \
+    int clients;                                                                           \
+    int conn_status = BT_STATUS_NOT_READY;                                                      \
+    for (clients = 0; clients < btif_max_rc_clients; clients++)                            \
+    {                                                                                      \
+        if ((btif_rc_cb[clients].rc_connected == TRUE))                                    \
+            conn_status = BT_STATUS_SUCCESS;                                                    \
+    }                                                                                      \
+    if(conn_status == BT_STATUS_NOT_READY)                                                      \
+    {                                                                                      \
         BTIF_TRACE_WARNING("Function %s() called when RC is not connected", __FUNCTION__); \
-        return BT_STATUS_NOT_READY;                                                         \
+        return BT_STATUS_NOT_READY;                                                        \
     }
 
-#define FILL_PDU_QUEUE(index, ctype, label, pending)        \
-{                                                           \
-    btif_rc_cb.rc_pdu_info[index].ctype = ctype;            \
-    btif_rc_cb.rc_pdu_info[index].label = label;            \
-    btif_rc_cb.rc_pdu_info[index].is_rsp_pending = pending; \
+#define TXN_LABEL_ENQUEUE(handle, label, front, rear, size, item, cmd)   \
+{                                                                        \
+    if (size == MAX_TRANSACTIONS_PER_SESSION)                            \
+    {                                                                    \
+        send_reject_response(handle, item, cmd, AVRC_STS_INTERNAL_ERR);  \
+        break;                                                           \
+    }                                                                    \
+    rear = (rear + 1) % MAX_TRANSACTIONS_PER_SESSION;                    \
+    label[rear] = item;                                                  \
+    size = size + 1;                                                     \
 }
 
-#define SEND_METAMSG_RSP(index, avrc_rsp)                                                      \
+#define TXN_LABEL_DEQUEUE(label, front, rear, size)        \
+{                                                          \
+    if (size == 0)                                         \
+        return BT_STATUS_UNHANDLED;                        \
+    front = (front + 1) % MAX_TRANSACTIONS_PER_SESSION;    \
+    size = size - 1;                                       \
+}
+
+#define FILL_PDU_QUEUE(idx, ctype, label, pending, index, cmd)                                 \
 {                                                                                              \
-    if (btif_rc_cb.rc_pdu_info[index].is_rsp_pending == FALSE)                                  \
+    btif_rc_cb[index].rc_pdu_info[idx].ctype[idx] = ctype;                                     \
+    TXN_LABEL_ENQUEUE(btif_rc_cb[index].rc_handle, btif_rc_cb[index].rc_pdu_info[idx].label,   \
+            btif_rc_cb[index].rc_pdu_info[idx].front, btif_rc_cb[index].rc_pdu_info[idx].rear, \
+            btif_rc_cb[index].rc_pdu_info[idx].size, label, cmd);                              \
+    BTIF_TRACE_DEBUG("%s txn label %d enqueued to txn queue of pdu %s, queue size %d \n",      \
+            __FUNCTION__, label, dump_rc_pdu(cmd), btif_rc_cb[index].rc_pdu_info[idx].size);   \
+    btif_rc_cb[index].rc_pdu_info[idx].is_rsp_pending = pending;                               \
+}
+
+#define SEND_METAMSG_RSP(idx, avrc_rsp, index)                                                 \
+{                                                                                              \
+    UINT8 curr_label = btif_rc_cb[index].rc_pdu_info[idx].label[                               \
+            btif_rc_cb[index].rc_pdu_info[idx].front];                                         \
+    if(btif_rc_cb[index].rc_pdu_info[idx].is_rsp_pending == FALSE)                             \
     {                                                                                          \
-        BTIF_TRACE_WARNING("%s Not sending response as no PDU was registered", __FUNCTION__); \
+        BTIF_TRACE_WARNING("%s Not sending response as no PDU was registered", __FUNCTION__);  \
         return BT_STATUS_UNHANDLED;                                                            \
     }                                                                                          \
-    send_metamsg_rsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_pdu_info[index].label,                \
-        btif_rc_cb.rc_pdu_info[index].ctype, avrc_rsp);                                        \
-    btif_rc_cb.rc_pdu_info[index].ctype = 0;                                                   \
-    btif_rc_cb.rc_pdu_info[index].label = 0;                                                   \
-    btif_rc_cb.rc_pdu_info[index].is_rsp_pending = FALSE;                                      \
+    TXN_LABEL_DEQUEUE(btif_rc_cb[index].rc_pdu_info[idx].label,                                \
+            btif_rc_cb[index].rc_pdu_info[idx].front,                                          \
+            btif_rc_cb[index].rc_pdu_info[idx].rear,                                           \
+            btif_rc_cb[index].rc_pdu_info[idx].size);                                          \
+    send_metamsg_rsp(btif_rc_cb[index].rc_handle, curr_label,                                  \
+            btif_rc_cb[index].rc_pdu_info[idx].ctype[idx], avrc_rsp);                          \
+    BTIF_TRACE_DEBUG("%s txn label %d dequeued from txn queue, queue sz %d \n", __FUNCTION__,  \
+            curr_label, btif_rc_cb[index].rc_pdu_info[idx].size);                              \
+    if (btif_rc_cb[index].rc_pdu_info[idx].size == 0)                                          \
+    {                                                                                          \
+        btif_rc_cb[index].rc_pdu_info[idx].ctype[idx] = 0;                                     \
+        btif_rc_cb[index].rc_pdu_info[idx].is_rsp_pending = FALSE;                             \
+    }                                                                                          \
+}
+
+#define SEND_BROWSEMSG_RSP(idx , avrc_rsp, index)                                              \
+{                                                                                              \
+    UINT8 curr_label = btif_rc_cb[index].rc_pdu_info[idx].label[                               \
+            btif_rc_cb[index].rc_pdu_info[idx].front];                                         \
+    if(btif_rc_cb[index].rc_pdu_info[idx].is_rsp_pending == FALSE)                             \
+    {                                                                                          \
+        BTIF_TRACE_WARNING("%s Not sending response as no PDU was registered", __FUNCTION__);  \
+        return BT_STATUS_UNHANDLED;                                                            \
+    }                                                                                          \
+    TXN_LABEL_DEQUEUE(btif_rc_cb[index].rc_pdu_info[idx].label,                                \
+            btif_rc_cb[index].rc_pdu_info[idx].front,                                          \
+            btif_rc_cb[index].rc_pdu_info[idx].rear,                                           \
+            btif_rc_cb[index].rc_pdu_info[idx].size);                                          \
+    send_browsemsg_rsp(btif_rc_cb[index].rc_handle, curr_label,                                \
+            btif_rc_cb[index].rc_pdu_info[idx].ctype[idx], avrc_rsp);                          \
+    BTIF_TRACE_DEBUG("%s txn label %d dequeued from txn queue, queue sz %d \n", __FUNCTION__,  \
+            curr_label, btif_rc_cb[index].rc_pdu_info[idx].size);                              \
+    if (btif_rc_cb[index].rc_pdu_info[idx].size == 0)                                          \
+    {                                                                                          \
+        btif_rc_cb[index].rc_pdu_info[idx].ctype[idx] = 0;                                     \
+        btif_rc_cb[index].rc_pdu_info[idx].is_rsp_pending = FALSE;                             \
+    }                                                                                          \
 }
 
 /*****************************************************************************
@@ -112,8 +201,11 @@
 
 typedef struct
 {
-    UINT8   label;
-    UINT8   ctype;
+    int front;
+    int rear;
+    int size;
+    UINT8 label[MAX_TRANSACTIONS_PER_SESSION];
+    UINT8 ctype[MAX_TRANSACTIONS_PER_SESSION];
     BOOLEAN is_rsp_pending;
 } btif_rc_cmd_ctxt_t;
 
@@ -183,6 +275,7 @@
     BOOLEAN                     rc_features_processed;
     UINT64                      rc_playing_uid;
     BOOLEAN                     rc_procedure_complete;
+    BOOLEAN                     rc_play_processed;
 } btif_rc_cb_t;
 
 typedef struct {
@@ -197,14 +290,17 @@
 {
     pthread_mutex_t lbllock;
     rc_transaction_t transaction[MAX_TRANSACTIONS_PER_SESSION];
+    BOOLEAN lbllock_destroyed;
 } rc_device_t;
 
 rc_device_t device;
 
 #define MAX_UINPUT_PATHS 3
+static int btif_max_rc_clients = 1;
 static const char* uinput_dev_path[] =
                        {"/dev/uinput", "/dev/input/uinput", "/dev/misc/uinput" };
 static int uinput_fd = -1;
+static BD_ADDR bd_null= {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
 static int  send_event (int fd, uint16_t type, uint16_t code, int32_t value);
 static void send_key (int fd, uint16_t key, int pressed);
@@ -236,7 +332,7 @@
 static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label,
     tBTA_AV_CODE code, tAVRC_RESPONSE *pmetamsg_resp);
 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
-static void register_volumechange(UINT8 label);
+static void register_volumechange(UINT8 label, int index);
 #endif
 static void lbl_init();
 static void lbl_destroy();
@@ -265,7 +361,6 @@
 static void handle_get_elem_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_ELEM_ATTRS_RSP *p_rsp);
 static void handle_set_app_attr_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_RSP *p_rsp);
 static bt_status_t get_play_status_cmd(void);
-static bt_status_t get_player_app_setting_attr_text_cmd (UINT8 *attrs, UINT8 num_attrs);
 static bt_status_t get_player_app_setting_value_text_cmd (UINT8 *vals, UINT8 num_vals);
 static bt_status_t register_notification_cmd (UINT8 label, UINT8 event_id, UINT32 event_value);
 static bt_status_t get_element_attribute_cmd (uint8_t num_attribute, uint32_t *p_attr_ids);
@@ -274,30 +369,51 @@
 static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id);
 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids);
 #endif
-static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND* p_param, UINT8 ctype, UINT8 label);
-#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
-static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label);
-#endif
 static void rc_start_play_status_timer(void);
 static bool absolute_volume_disabled(void);
+static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND* p_param, UINT8 ctype, UINT8 label,
+                                    int index);
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
+static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label,
+                                    int index);
+#endif
+static bt_status_t set_addrplayer_rsp(btrc_status_t status_code, bt_bdaddr_t *bd_addr);
+static int btif_rc_get_idx_by_addr(BD_ADDR address);
+
+/*Added for Browsing Message Response */
+static void send_browsemsg_rsp (UINT8 rc_handle, UINT8 label,
+    tBTA_AV_CODE code, tAVRC_RESPONSE *pmetamsg_resp);
+
 static char const* key_id_to_str(uint16_t id);
 
 /*****************************************************************************
 **  Static variables
 ******************************************************************************/
-static btif_rc_cb_t btif_rc_cb;
+/* Two RC CBs needed to handle two connections*/
+static btif_rc_cb_t btif_rc_cb[BTIF_RC_NUM_CB];
 static btrc_callbacks_t *bt_rc_callbacks = NULL;
 static btrc_ctrl_callbacks_t *bt_rc_ctrl_callbacks = NULL;
 
 /*****************************************************************************
 **  Static functions
 ******************************************************************************/
+static UINT8 btif_rc_get_idx_by_rc_handle(UINT8 rc_handle);
 
 /*****************************************************************************
 **  Externs
 ******************************************************************************/
 extern BOOLEAN btif_hf_call_terminated_recently();
 extern BOOLEAN check_cod(const bt_bdaddr_t *remote_bdaddr, uint32_t cod);
+extern void btif_get_latest_playing_device(BD_ADDR address); //get the Playing device address
+extern BOOLEAN btif_av_is_playing();
+extern BOOLEAN btif_av_is_device_connected(BD_ADDR address);
+extern void btif_av_trigger_dual_handoff(BOOLEAN handoff, BD_ADDR address);
+extern BOOLEAN btif_hf_is_call_vr_idle();
+extern BOOLEAN btif_av_is_current_device(BD_ADDR address);
+extern UINT16 btif_av_get_num_connected_devices(void);
+extern UINT16 btif_av_get_num_playing_devices(void);
+extern BOOLEAN btif_av_is_offload_supported();
+extern UINT8 btif_av_idx_by_bdaddr(BD_ADDR bd_addr);
 
 extern fixed_queue_t *btu_general_alarm_queue;
 
@@ -370,7 +486,7 @@
     }
     memset(&dev, 0, sizeof(dev));
     if (name)
-        strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE-1);
+        strlcpy(dev.name, name, UINPUT_MAX_NAME_SIZE-1);
 
     dev.id.bustype = BUS_BLUETOOTH;
     dev.id.vendor  = 0x0000;
@@ -397,6 +513,8 @@
         close(fd);
         return -1;
     }
+    BTIF_TRACE_IMP("AVRCP: input device opened.. Delay 30 ms");
+    sleep_ms(30);
     return fd;
 }
 
@@ -405,19 +523,27 @@
     char *name = "AVRCP";
 
     BTIF_TRACE_DEBUG("%s", __FUNCTION__);
-    uinput_fd = uinput_create(name);
-    if (uinput_fd < 0) {
-        BTIF_TRACE_ERROR("%s AVRCP: Failed to initialize uinput for %s (%d)",
-                          __FUNCTION__, name, uinput_fd);
-    } else {
-        BTIF_TRACE_DEBUG("%s AVRCP: Initialized uinput for %s (fd=%d)",
-                          __FUNCTION__, name, uinput_fd);
+    if (uinput_fd < 0)
+    {
+        BTIF_TRACE_DEBUG("Create Uinput device");
+        uinput_fd = uinput_create(name);
+        if (uinput_fd < 0) {
+            BTIF_TRACE_ERROR("%s AVRCP: Failed to initialize uinput for %s (%d)",
+                            __FUNCTION__, name, uinput_fd);
+        }
+        else
+        {
+            BTIF_TRACE_DEBUG("%s AVRCP: Initialized uinput for %s (fd=%d)",
+                            __FUNCTION__, name, uinput_fd);
+        }
     }
     return uinput_fd;
 }
 
 void close_uinput (void)
 {
+    //Dont close uinput untill all connections are teared down
+    // Since we support Dual AVRCP conn now.
     BTIF_TRACE_DEBUG("%s", __FUNCTION__);
     if (uinput_fd > 0) {
         ioctl(uinput_fd, UI_DEV_DESTROY);
@@ -427,6 +553,7 @@
     }
 }
 
+
 #if (AVRC_CTLR_INCLUDED == TRUE)
 void rc_cleanup_sent_cmd (void *p_data)
 {
@@ -434,119 +561,280 @@
 
 }
 
-void handle_rc_ctrl_features(BD_ADDR bd_addr)
+void handle_rc_ctrl_features(int index)
 {
-    if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
-       ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
-        (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
+    if ((btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG)||
+       ((btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCCT)&&
+        (btif_rc_cb[index].rc_features & BTA_AV_FEAT_ADV_CTRL)))
     {
         bt_bdaddr_t rc_addr;
         int rc_features = 0;
-        bdcpy(rc_addr.address,bd_addr);
+        bdcpy(rc_addr.address, btif_rc_cb[index].rc_addr);
 
-        if ((btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)&&
-             (btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT))
+        if ((btif_rc_cb[index].rc_features & BTA_AV_FEAT_ADV_CTRL)&&
+             (btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCCT))
         {
             rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
         }
-        if ((btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)&&
-            (btif_rc_cb.rc_features & BTA_AV_FEAT_VENDOR)&&
-            (btif_rc_cb.rc_features_processed != TRUE))
+        if ((btif_rc_cb[index].rc_features & BTA_AV_FEAT_METADATA)&&
+            (btif_rc_cb[index].rc_features & BTA_AV_FEAT_VENDOR)&&
+            (btif_rc_cb[index].rc_features_processed != TRUE))
         {
             rc_features |= BTRC_FEAT_METADATA;
             /* Mark rc features processed to avoid repeating
              * the AVRCP procedure every time on receiving this
              * update.
              */
-            btif_rc_cb.rc_features_processed = TRUE;
-
-            if (btif_av_is_sink_enabled())
+            if ((btif_rc_cb[index].rc_features_processed == FALSE) &&
+                btif_av_is_sink_enabled())
+            {
+                btif_rc_cb[index].rc_features_processed = TRUE;
                 getcapabilities_cmd (AVRC_CAP_COMPANY_ID);
+            }
         }
         BTIF_TRACE_DEBUG("%s Update rc features to CTRL %d", __FUNCTION__, rc_features);
-        HAL_CBACK(bt_rc_ctrl_callbacks, getrcfeatures_cb, &rc_addr, rc_features);
+        if (btif_av_is_sink_enabled()) {
+            HAL_CBACK(bt_rc_ctrl_callbacks, getrcfeatures_cb, &rc_addr, rc_features);
+        }
     }
 }
 #endif
 
-void handle_rc_features(BD_ADDR bd_addr)
+void handle_rc_features(int index)
 {
     if (bt_rc_callbacks != NULL)
     {
-    btrc_remote_features_t rc_features = BTRC_FEAT_NONE;
-    bt_bdaddr_t rc_addr;
+        btrc_remote_features_t rc_features = BTRC_FEAT_NONE;
+        bt_bdaddr_t rc_addr;
+        bt_bdaddr_t avdtp_addr;
+        bdstr_t addr1, addr2;
 
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
-    bt_bdaddr_t avdtp_addr  = btif_av_get_addr();
+        bdcpy(rc_addr.address, btif_rc_cb[index].rc_addr);
+        avdtp_addr = btif_av_get_addr(btif_rc_cb[index].rc_addr);
 
-    bdstr_t addr1, addr2;
-    BTIF_TRACE_DEBUG("%s: AVDTP Address: %s AVCTP address: %s", __func__,
-                     bdaddr_to_string(&avdtp_addr, addr1, sizeof(addr1)),
-                     bdaddr_to_string(&rc_addr, addr2, sizeof(addr2)));
+        BTIF_TRACE_DEBUG("AVDTP Address : %s AVCTP address: %s",
+                         bdaddr_to_string(&avdtp_addr, addr1, sizeof(bdstr_t)),
+                         bdaddr_to_string(&rc_addr, addr2, sizeof(bdstr_t)) );
 
-    if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr)
-        || absolute_volume_disabled()
-        || bdcmp(avdtp_addr.address, rc_addr.address))
-        btif_rc_cb.rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
+        if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, (bt_bdaddr_t *)&rc_addr)
+                || absolute_volume_disabled()
+                || bdcmp(avdtp_addr.address, rc_addr.address))
+            btif_rc_cb[index].rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
 
-    if (btif_rc_cb.rc_features & BTA_AV_FEAT_BROWSE)
-    {
-        rc_features |= BTRC_FEAT_BROWSE;
-    }
-
+        if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_BROWSE)
+        {
+            rc_features |= BTRC_FEAT_BROWSE;
+        }
+        if ( (btif_rc_cb[index].rc_features & BTA_AV_FEAT_ADV_CTRL) &&
+            (btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG))
+        {
+            rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
+        }
+        if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_METADATA)
+        {
+            rc_features |= BTRC_FEAT_METADATA;
+        }
+        if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_AVRC_UI_UPDATE)
+        {
+            rc_features |= BTRC_FEAT_AVRC_UI_UPDATE;
+        }
+        BTIF_TRACE_IMP("%s: rc_features=0x%x", __FUNCTION__, rc_features);
+        if (btif_rc_cb[index].rc_connected)
+        {
+            BTIF_TRACE_IMP("%s: update App on supported features", __FUNCTION__);
+            HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features)
+        }
+        else
+        {
+            BTIF_TRACE_IMP("%s: skipping feature update to App", __FUNCTION__);
+        }
 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
-    if ( (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL) &&
-         (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG))
-    {
-        rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
-    }
-#endif
-
-    if (btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)
-    {
-        rc_features |= BTRC_FEAT_METADATA;
-    }
-
-    BTIF_TRACE_DEBUG("%s: rc_features=0x%x", __FUNCTION__, rc_features);
-    HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features)
-
-#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
-     BTIF_TRACE_DEBUG("%s Checking for feature flags in btif_rc_handler with label %d",
-                        __FUNCTION__, btif_rc_cb.rc_vol_label);
-     // Register for volume change on connect
-      if (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL &&
-         btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
-      {
-         rc_transaction_t *p_transaction=NULL;
-         bt_status_t status = BT_STATUS_NOT_READY;
-         if (MAX_LABEL==btif_rc_cb.rc_vol_label)
-         {
-            status=get_transaction(&p_transaction);
-         }
-         else
-         {
-            p_transaction=get_transaction_by_lbl(btif_rc_cb.rc_vol_label);
-            if (NULL!=p_transaction)
+        BTIF_TRACE_DEBUG("Checking for feature flags in btif_rc_handler with label %d",
+                         btif_rc_cb[index].rc_vol_label);
+        // Register for volume change on connect
+        if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_ADV_CTRL &&
+            btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG)
+        {
+            rc_transaction_t *p_transaction=NULL;
+            bt_status_t status = BT_STATUS_NOT_READY;
+            if (MAX_LABEL == btif_rc_cb[index].rc_vol_label)
             {
-               BTIF_TRACE_DEBUG("%s register_volumechange already in progress for label %d",
-                                  __FUNCTION__, btif_rc_cb.rc_vol_label);
-               return;
+                status=get_transaction(&p_transaction);
             }
             else
-              status=get_transaction(&p_transaction);
-         }
+            {
+                p_transaction=get_transaction_by_lbl(btif_rc_cb[index].rc_vol_label);
+                if (NULL != p_transaction)
+                {
+                    BTIF_TRACE_DEBUG("register_volumechange already in progress for label %d",
+                    btif_rc_cb[index].rc_vol_label);
+                    return;
+                }
+                else
+                    status = get_transaction(&p_transaction);
+            }
 
-         if (BT_STATUS_SUCCESS == status && NULL!=p_transaction)
-         {
-            btif_rc_cb.rc_vol_label=p_transaction->lbl;
-            register_volumechange(btif_rc_cb.rc_vol_label);
-         }
-       }
+            if (BT_STATUS_SUCCESS == status && NULL!=p_transaction)
+            {
+                btif_rc_cb[index].rc_vol_label=p_transaction->lbl;
+                register_volumechange(btif_rc_cb[index].rc_vol_label, index);
+            }
+        }
 #endif
     }
 }
 
 /***************************************************************************
+ *  Function       btif_rc_init_txn_label_queue
+ *
+ *  - Argument:    index of rc control block
+ *
+ *  - Description: initializes the txn label queues for the rc index
+ *
+ ***************************************************************************/
+void btif_rc_init_txn_label_queue(int index)
+{
+    int j;
+    for (j = 0; j < MAX_CMD_QUEUE_LEN; j++)
+    {
+        btif_rc_cb[index].rc_pdu_info[j].front = 0;
+        btif_rc_cb[index].rc_pdu_info[j].size = 0;
+        btif_rc_cb[index].rc_pdu_info[j].rear = MAX_TRANSACTIONS_PER_SESSION - 1;
+    }
+}
+
+/***************************************************************************
+ *  Function       btif_rc_get_connection_state
+ *
+ *  - Argument:    none
+ *
+ *  - Description: Return true if any RC is in connected state
+ *
+ ***************************************************************************/
+static BOOLEAN btif_rc_get_connection_state()
+{
+    int clients;
+
+    for (clients = 0; clients < btif_max_rc_clients; clients++)
+    {
+        if (btif_rc_cb[clients].rc_connected == TRUE)
+        {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/***************************************************************************
+ *  Function       btif_rc_get_valid_idx
+ *
+ *  - Argument:    none
+ *
+ *  - Description: Gets the index which is ready for new connection
+ *
+ ***************************************************************************/
+static int btif_rc_get_valid_idx()
+{
+    int i;
+    for (i = 0; i < btif_max_rc_clients; i++)
+    {
+        if (!(btif_rc_cb[i].rc_connected))
+            break;
+    }
+    return i;
+}
+
+/***************************************************************************
+ *  Function       btif_rc_get_idx_by_rc_handle
+ *
+ *  - Argument:    rc handle
+ *
+ *  - Description: Gets the RC handle index of matching handle
+ *
+ ***************************************************************************/
+static UINT8 btif_rc_get_idx_by_rc_handle(UINT8 rc_handle)
+{
+    UINT8 i;
+
+    for (i = 0; i < btif_max_rc_clients; i++)
+    {
+        if (btif_rc_cb[i].rc_handle == rc_handle)
+            break;
+    }
+    return i;
+}
+
+/* Get the address of device on which PLAY command came
+* This address will be used in AV IF layer to determine
+* On which device to START playback. */
+/***************************************************************************
+ *  Function       btif_rc_get_playing_device
+ *
+ *  - Argument:    bd_addr
+ *
+ *  - Description: Copies the BD address of current playing device
+ *
+ ***************************************************************************/
+void btif_rc_get_playing_device(BD_ADDR address)
+{
+    int i;
+    for (i = 0; i < btif_max_rc_clients; i++)
+    {
+        if (btif_rc_cb[i].rc_play_processed)
+        {
+            //copy bd address
+            bdcpy(address, btif_rc_cb[i].rc_addr);
+        }
+    }
+}
+
+/* Reset the Play trigger, once the AVDTP START is
+* sent, called from AV IF layer. */
+/***************************************************************************
+ *  Function       btif_rc_clear_playing_state
+ *
+ *  - Argument:    BOOLEAN
+ *
+ *  - Description: Clears the PLAY processed.rc_play_processed denotes
+ *                 play command has been processed for this device.
+ *
+ ***************************************************************************/
+void btif_rc_clear_playing_state(BOOLEAN state)
+{
+    int i;
+    for (i = 0; i < btif_max_rc_clients; i++)
+    {
+        if (btif_rc_cb[i].rc_play_processed)
+        {
+            btif_rc_cb[i].rc_play_processed = state;
+        }
+    }
+}
+
+/***************************************************************************
+ *  Function       btif_rc_clear_priority
+ *
+ *  - Argument:    Device address
+ *
+ *  - Description: Clears the priority information for the device
+ *                 This can be used while AV disconnection for the device.
+ *                 Setting of rc_play_processed flag could have been avoided
+ *                 looking at the stream state, but it might still leave some
+ *                 corner case of audio suspending just before the play takes
+ *                 effect.
+ ***************************************************************************/
+void btif_rc_clear_priority(BD_ADDR address)
+{
+    int index;
+
+    index = btif_rc_get_idx_by_addr(address);
+    if(index < btif_max_rc_clients)
+    {
+        btif_rc_cb[index].rc_play_processed = FALSE;
+    }
+}
+
+/***************************************************************************
  *  Function       handle_rc_connect
  *
  *  - Argument:    tBTA_AV_RC_OPEN  RC open data structure
@@ -556,73 +844,77 @@
  ***************************************************************************/
 void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open)
 {
-    BTIF_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_open->rc_handle);
+    BTIF_TRACE_IMP("%s: rc_handle: %d", __FUNCTION__, p_rc_open->rc_handle);
     bt_status_t result = BT_STATUS_SUCCESS;
-#if (AVRC_CTLR_INCLUDED == TRUE)
     bt_bdaddr_t rc_addr;
-#endif
-
-    if (p_rc_open->status == BTA_AV_SUCCESS)
+    int index;
+    if(p_rc_open->status == BTA_AV_SUCCESS)
     {
-        //check if already some RC is connected
-        if (btif_rc_cb.rc_connected)
+        //Check if already some RC is connected
+        /*Now we can have two RC connections
+        * Check should be here about 3rd connection too.
+        * Get the free or MAX index. Max index should be rejected. */
+        index = btif_rc_get_valid_idx();
+        if (index == btif_max_rc_clients)
         {
-            BTIF_TRACE_ERROR("%s Got RC OPEN in connected state, Connected RC: %d \
-                and Current RC: %d", __FUNCTION__, btif_rc_cb.rc_handle,p_rc_open->rc_handle );
-            if ((btif_rc_cb.rc_handle != p_rc_open->rc_handle)
-                && (bdcmp(btif_rc_cb.rc_addr, p_rc_open->peer_addr)))
-            {
-                BTIF_TRACE_DEBUG("%s Got RC connected for some other handle", __FUNCTION__);
-                BTA_AvCloseRc(p_rc_open->rc_handle);
-                return;
-            }
+            /*Reached Max, this connection must be rejected*/
+            BTIF_TRACE_ERROR("RC OPEN in MAX connected state");
+            BTA_AvCloseRc(p_rc_open->rc_handle);
+            return;
         }
-        memcpy(btif_rc_cb.rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR));
-        btif_rc_cb.rc_features = p_rc_open->peer_features;
-        btif_rc_cb.rc_vol_label=MAX_LABEL;
-        btif_rc_cb.rc_volume=MAX_VOLUME;
+        /*Use the index for this RC connection*/
+        BTIF_TRACE_DEBUG("Got RC OPEN on the index= %d", index);
+        memcpy(btif_rc_cb[index].rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR));
+        btif_rc_cb[index].rc_features = p_rc_open->peer_features;
+        btif_rc_cb[index].rc_vol_label = MAX_LABEL;
+        btif_rc_cb[index].rc_volume = MAX_VOLUME;
+        btif_rc_cb[index].rc_connected = TRUE;
+        btif_rc_cb[index].rc_handle = p_rc_open->rc_handle;
+        btif_rc_init_txn_label_queue(index);
 
-        btif_rc_cb.rc_connected = TRUE;
-        btif_rc_cb.rc_handle = p_rc_open->rc_handle;
-
-        /* on locally initiated connection we will get remote features as part of connect */
-        if (btif_rc_cb.rc_features != 0)
-            handle_rc_features(btif_rc_cb.rc_addr);
         if (bt_rc_callbacks)
         {
             result = uinput_driver_check();
-            if (result == BT_STATUS_SUCCESS)
+            if(result == BT_STATUS_SUCCESS)
             {
                 init_uinput();
             }
         }
         else
         {
-            BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not initializing UInput",
-                               __FUNCTION__);
+            BTIF_TRACE_WARNING("Avrcp TG role not enabled, not initializing UInput");
         }
-        BTIF_TRACE_DEBUG("%s handle_rc_connect features %d ",__FUNCTION__, btif_rc_cb.rc_features);
+        bdcpy(rc_addr.address, btif_rc_cb[index].rc_addr);
+        if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCCT)
+        {
+            HAL_CBACK(bt_rc_callbacks, connection_state_cb, TRUE, &rc_addr);
+        }
+        /* on locally initiated connection we will get remote features as part of connect */
+        if (btif_rc_cb[index].rc_features != 0)
+            handle_rc_features(index);
+        BTIF_TRACE_DEBUG(" handle_rc_connect features %d ",btif_rc_cb[index].rc_features);
 #if (AVRC_CTLR_INCLUDED == TRUE)
-        btif_rc_cb.rc_playing_uid = RC_INVALID_TRACK_ID;
-        bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+        btif_rc_cb[index].rc_playing_uid = RC_INVALID_TRACK_ID;
+        bdcpy(rc_addr.address, btif_rc_cb[index].rc_addr);
         if (bt_rc_ctrl_callbacks != NULL)
         {
             HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, TRUE, &rc_addr);
         }
         /* report connection state if remote device is AVRCP target */
-        if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
-           ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
-            (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
+        if ((btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG)||
+           ((btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCCT)&&
+            (btif_rc_cb[index].rc_features & BTA_AV_FEAT_ADV_CTRL)))
         {
-            handle_rc_ctrl_features(btif_rc_cb.rc_addr);
+            handle_rc_ctrl_features(index);
         }
 #endif
+        /* on locally initiated connection we will get remote features as part of connect
+        Delay this update till connection update reaches Apps*/
     }
     else
     {
         BTIF_TRACE_ERROR("%s Connect failed with error code: %d",
             __FUNCTION__, p_rc_open->status);
-        btif_rc_cb.rc_connected = FALSE;
     }
 }
 
@@ -636,52 +928,52 @@
  ***************************************************************************/
 void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
 {
-#if (AVRC_CTLR_INCLUDED == TRUE)
     bt_bdaddr_t rc_addr;
     tBTA_AV_FEAT features;
-#endif
-    BTIF_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_close->rc_handle);
-    if ((p_rc_close->rc_handle != btif_rc_cb.rc_handle)
-        && (bdcmp(btif_rc_cb.rc_addr, p_rc_close->peer_addr)))
+    UINT8 index;
+    BOOLEAN is_connected = 0;
+
+    BTIF_TRACE_IMP("%s: rc_handle: %d", __FUNCTION__, p_rc_close->rc_handle);
+
+    index = btif_rc_get_idx_by_rc_handle(p_rc_close->rc_handle);
+    if (index == btif_max_rc_clients)
     {
         BTIF_TRACE_ERROR("Got disconnect of unknown device");
         return;
     }
-#if (AVRC_CTLR_INCLUDED == TRUE)
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
-    features = btif_rc_cb.rc_features;
-        /* Clean up AVRCP procedure flags */
-    memset(&btif_rc_cb.rc_app_settings, 0,
-        sizeof(btif_rc_player_app_settings_t));
-    btif_rc_cb.rc_features_processed = FALSE;
-    btif_rc_cb.rc_procedure_complete = FALSE;
-    rc_stop_play_status_timer();
-    /* Check and clear the notification event list */
-    if (btif_rc_cb.rc_supported_event_list != NULL)
+    if ((p_rc_close->rc_handle != btif_rc_cb[index].rc_handle)
+        && (bdcmp(btif_rc_cb[index].rc_addr, p_rc_close->peer_addr)))
     {
-        list_clear(btif_rc_cb.rc_supported_event_list);
-        btif_rc_cb.rc_supported_event_list = NULL;
+        BTIF_TRACE_ERROR("Got disconnect of unknown device");
+        return;
     }
-#endif
-    btif_rc_cb.rc_handle = 0;
-    btif_rc_cb.rc_connected = FALSE;
-    memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
-    memset(btif_rc_cb.rc_notif, 0, sizeof(btif_rc_cb.rc_notif));
+    btif_rc_cb[index].rc_handle = BTIF_RC_HANDLE_NONE;
+    btif_rc_cb[index].rc_connected = FALSE;
+    bdcpy(rc_addr.address, btif_rc_cb[index].rc_addr);
+    memset(btif_rc_cb[index].rc_addr, 0, sizeof(BD_ADDR));
+    memset(btif_rc_cb[index].rc_notif, 0, sizeof(btif_rc_cb[index].rc_notif));
+    features = btif_rc_cb[index].rc_features;
+    btif_rc_cb[index].rc_features = 0;
+    btif_rc_cb[index].rc_vol_label = MAX_LABEL;
+    btif_rc_cb[index].rc_volume = MAX_VOLUME;
+    btif_rc_cb[index].rc_play_processed = FALSE;
+    btif_rc_cb[index].rc_pending_play = FALSE;
+    btif_rc_init_txn_label_queue(index);
 
-    btif_rc_cb.rc_features = 0;
-    btif_rc_cb.rc_vol_label=MAX_LABEL;
-    btif_rc_cb.rc_volume=MAX_VOLUME;
-    init_all_transactions();
-    if (bt_rc_callbacks != NULL)
+    //CLose Uinput only when all RCs are disconnected
+    is_connected = btif_rc_get_connection_state();
+    BTIF_TRACE_DEBUG("RC connected : %d", is_connected);
+	if (is_connected != TRUE && device.lbllock_destroyed != TRUE)
     {
+        BTIF_TRACE_DEBUG("Clear UINPUT and transactions when zero RC left");
+        init_all_transactions();
         close_uinput();
     }
-    else
+    if (!bdcmp(bd_null, rc_addr.address))
     {
-        BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not closing UInput", __FUNCTION__);
+        BTIF_TRACE_DEBUG("Cleanup already done");
+        return;
     }
-
-    memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
 #if (AVRC_CTLR_INCLUDED == TRUE)
     /* report connection state if device is AVRCP target */
     if (bt_rc_ctrl_callbacks != NULL)
@@ -689,6 +981,10 @@
         HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, FALSE, &rc_addr);
    }
 #endif
+    if (features & BTA_AV_FEAT_RCCT)
+    {
+        HAL_CBACK(bt_rc_callbacks, connection_state_cb, FALSE, &rc_addr);
+    }
 }
 
 /***************************************************************************
@@ -700,11 +996,88 @@
  *  - Description: Remote control command handler
  *
  ***************************************************************************/
+
+/* Rules: Only currenlty playing device's Passthrough commands
+* will be entertained.
+* While playing on Dev 1, if Dev2 sends Play, just respond it
+* without passing it to APP and in parallel start a protocol
+* suspend/pause the playback on DEV1 and Start on DEV2
+* Making sure that music is not paused and transfer happens seamless. */
 void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd)
 {
     const char *status;
     int pressed, i;
+    UINT8 index;
+    BD_ADDR address;
+    bt_bdaddr_t remote_address;
+    BOOLEAN ignore_play_processed = FALSE;
 
+    if (p_remote_cmd == NULL)
+        return;
+
+    index = btif_rc_get_idx_by_rc_handle(p_remote_cmd->rc_handle);
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("Passthrough on invalid index");
+        return;
+    }
+    /* Multicast: Passthru command on AVRCP only device when connected
+     * to other A2DP devices, ignore it.
+     */
+    if (btif_av_is_connected() && !btif_av_is_device_connected(btif_rc_cb[index].rc_addr))
+    {
+        BTIF_TRACE_ERROR("Passthrough on AVRCP only device: Ignore..");
+        return;
+    }
+
+    /* Trigger DUAL Handoff when support single streaming */
+    if (btif_av_is_playing() &&
+        (btif_av_get_multicast_state() == FALSE))
+    {
+        /*compare the bd addr of current playing dev and this dev*/
+        btif_get_latest_playing_device(address);
+        if (bdcmp(btif_rc_cb[index].rc_addr, address) == 0)
+        {
+            APPL_TRACE_WARNING("Passthrough on the playing device");
+            if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY) &&
+                (p_remote_cmd->key_state == AVRC_STATE_PRESS))
+            {
+                APPL_TRACE_WARNING("Play again");
+                ignore_play_processed = TRUE;
+            }
+        }
+        else
+        {
+            BTIF_TRACE_DEBUG("Passthrough command on other device");
+            if (p_remote_cmd->rc_id == BTA_AV_RC_PLAY)
+            {
+                if (btif_av_is_device_connected(btif_rc_cb[index].rc_addr))
+                {
+                    /* Trigger suspend on currently playing device
+                     * Allow the Play to be sent to Music player to
+                     * address Play during Pause(Local/DUT initiated)
+                     * but SUSPEND not triggered by Audio module.
+                     */
+                    if (p_remote_cmd->key_state == AVRC_STATE_PRESS)
+                    {
+                        BTIF_TRACE_DEBUG("Trigger dual handoff for this play command");
+                        btif_rc_cb[index].rc_play_processed = TRUE;
+                        btif_av_trigger_dual_handoff(TRUE, btif_rc_cb[index].rc_addr);
+                    }
+                }
+                else
+                {
+                    APPL_TRACE_WARNING("%s: Command Invalid on %d", __FUNCTION__, index);
+                    return;
+                }
+            }
+            else
+            {
+                APPL_TRACE_WARNING("%s:Ignore all Passthrough on %d", __FUNCTION__, index);
+                return;
+            }
+        }
+    }
     BTIF_TRACE_DEBUG("%s: p_remote_cmd->rc_id=%d", __FUNCTION__, p_remote_cmd->rc_id);
 
     /* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up this PLAY */
@@ -716,15 +1089,15 @@
             if (p_remote_cmd->key_state == AVRC_STATE_PRESS)
             {
                 APPL_TRACE_WARNING("%s: AVDT not open, queuing the PLAY command", __FUNCTION__);
-                btif_rc_cb.rc_pending_play = TRUE;
+                btif_rc_cb[index].rc_pending_play = TRUE;
             }
             return;
         }
 
-        if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (btif_rc_cb.rc_pending_play))
+        if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (btif_rc_cb[index].rc_pending_play))
         {
             APPL_TRACE_WARNING("%s: Clear the pending PLAY on PAUSE received", __FUNCTION__);
-            btif_rc_cb.rc_pending_play = FALSE;
+            btif_rc_cb[index].rc_pending_play = FALSE;
             return;
         }
         if ((p_remote_cmd->rc_id == BTA_AV_RC_VOL_UP)||(p_remote_cmd->rc_id == BTA_AV_RC_VOL_DOWN))
@@ -736,20 +1109,35 @@
         APPL_TRACE_WARNING("%s: Stream suspended, ignore STOP cmd",__FUNCTION__);
         return;
     }
+    if(!btif_av_is_connected())
+    {
+        APPL_TRACE_WARNING("%s: AVDT not open, discarding pass-through command: %d",
+                                                        __FUNCTION__, p_remote_cmd->rc_id);
+        return;
+    }
 
     if (p_remote_cmd->key_state == AVRC_STATE_RELEASE) {
         status = "released";
         pressed = 0;
-    } else {
+    }
+    else
+    {
         status = "pressed";
         pressed = 1;
     }
 
     if (p_remote_cmd->rc_id == BTA_AV_RC_FAST_FOR || p_remote_cmd->rc_id == BTA_AV_RC_REWIND) {
-        HAL_CBACK(bt_rc_callbacks, passthrough_cmd_cb, p_remote_cmd->rc_id, pressed);
+        bdcpy(remote_address.address, btif_rc_cb[index].rc_addr);
+        HAL_CBACK(bt_rc_callbacks, passthrough_cmd_cb, p_remote_cmd->rc_id, pressed, &remote_address);
         return;
     }
-
+    /*Update the device on which PLAY is issued*/
+    if (p_remote_cmd->rc_id == BTA_AV_RC_PLAY)
+    {
+        BTIF_TRACE_DEBUG("PLAY command on the Index: = %d", index);
+        if (p_remote_cmd->key_state == AVRC_STATE_PRESS && !ignore_play_processed)
+            btif_rc_cb[index].rc_play_processed = TRUE;
+    }
     for (i = 0; key_map[i].name != NULL; i++) {
         if (p_remote_cmd->rc_id == key_map[i].avrcp) {
             BTIF_TRACE_DEBUG("%s: %s %s", __FUNCTION__, key_map[i].name, status);
@@ -780,8 +1168,37 @@
     }
 
     if (key_map[i].name == NULL)
+    {
         BTIF_TRACE_ERROR("%s AVRCP: unknown button 0x%02X %s", __FUNCTION__,
                         p_remote_cmd->rc_id, status);
+    }
+    else
+    {
+        BTIF_TRACE_ERROR("%s AVRCP:send passthrough cmd = %s to BT Apps ",
+                        __FUNCTION__, key_map[i].name);
+        bdcpy(remote_address.address, btif_rc_cb[index].rc_addr);
+        HAL_CBACK(bt_rc_callbacks, passthrough_cmd_cb, p_remote_cmd->rc_id, pressed, &remote_address);
+    }
+}
+
+/***************************************************************************
+ *  Function       btif_rc_send_pause_command
+ *
+ *  - Argument:    None
+ *
+ *  - Description: Sends PAUSE key event to Upper layer.
+ *
+ ***************************************************************************/
+void btif_rc_send_pause_command()
+{
+    int rc_id;
+
+    rc_id = BTA_AV_RC_PAUSE;
+    BTIF_TRACE_DEBUG("Send Pause to music if playing is remotely disconnected");
+
+    send_key(uinput_fd, KEY_PAUSECD, 1);
+    sleep_ms(30); // 30ms
+    send_key(uinput_fd, KEY_PAUSECD, 0);
 }
 
 /***************************************************************************
@@ -796,7 +1213,8 @@
 {
 #if (AVRC_CTLR_INCLUDED == TRUE)
     const char *status;
-    if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
+    int index = BTIF_RC_DEFAULT_INDEX; // 0th index is RC
+    if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG)
     {
         int key_state;
         if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
@@ -839,7 +1257,8 @@
 #if (AVRC_CTLR_INCLUDED == TRUE)
     const char *status;
     UINT8 vendor_id = 0;
-    if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
+    int index = BTIF_RC_DEFAULT_INDEX; // 0th index is RC
+    if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG)
     {
         int key_state;
         if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
@@ -903,6 +1322,15 @@
     UINT8             scratch_buf[512] = {0};
     tAVRC_COMMAND    avrc_command = {0};
     tAVRC_STS status;
+    UINT8 index;
+
+    //Get the index of RC
+    index = btif_rc_get_idx_by_rc_handle(pmeta_msg->rc_handle);
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: Invalid RC index", __FUNCTION__);
+        return;
+    }
 
     BTIF_TRACE_EVENT("+ %s", __FUNCTION__);
 
@@ -964,8 +1392,8 @@
             UINT8 event_id = avrc_command.reg_notif.event_id;
             BTIF_TRACE_EVENT("%s:New register notification received.event_id:%s,label:0x%x,code:%x",
             __FUNCTION__,dump_rc_notification_event_id(event_id), pmeta_msg->label,pmeta_msg->code);
-            btif_rc_cb.rc_notif[event_id-1].bNotify = TRUE;
-            btif_rc_cb.rc_notif[event_id-1].label = pmeta_msg->label;
+            btif_rc_cb[index].rc_notif[event_id-1].bNotify = TRUE;
+            btif_rc_cb[index].rc_notif[event_id-1].label = pmeta_msg->label;
 
             if (event_id == AVRC_EVT_UIDS_CHANGE)
             {
@@ -982,10 +1410,306 @@
             *btif context, no context switching is required. Invoke
             * btif_rc_upstreams_evt directly from here. */
         btif_rc_upstreams_evt((uint16_t)avrc_command.cmd.pdu, &avrc_command, pmeta_msg->code,
-                               pmeta_msg->label);
+                               pmeta_msg->label, index);
     }
 }
 
+/************************************************************************************
+*  Function                 handle_get_folder_item_mediaplyerlist_cmd
+*
+* - Argument:               tBTA_AV_BROWSE_MSG  structure containing  the received
+*                           browse message
+*                           tAVRC_COMMAND       structure containing the commands
+*                           to be updated
+*                           UINT8 event,        variable having value of event.
+*
+*  - Description:           Handler for get media player list command
+*
+************************************************************************************/
+UINT8 handle_get_folder_item_mediaplyerlist_cmd (tBTA_AV_BROWSE_MSG *pbrowse_msg,
+                                                        tAVRC_COMMAND *cmd, UINT8 *event)
+{
+    UINT8 *p_length, *start_item, *end_item;
+    UINT8 length, xx;
+    *event = pbrowse_msg->p_msg->browse.p_browse_data[0] ;
+    cmd->get_items.pdu = *event;
+    //Check length
+    p_length = &pbrowse_msg->p_msg->browse.p_browse_data[1];
+    BE_STREAM_TO_UINT16(length, p_length);
+    if (length < 10)
+    {
+        BTIF_TRACE_ERROR("GET_FOLDER_ITEMS: length error: =%d",length);
+        return TRUE;
+    }
+    else
+    {
+        start_item = &pbrowse_msg->p_msg->browse.p_browse_data[4];
+        BE_STREAM_TO_UINT32(cmd->get_items.start_item ,start_item);
+        BTIF_TRACE_EVENT("pbrowse_msg start_item :%x",cmd->get_items.start_item);
+        end_item  =  &pbrowse_msg->p_msg->browse.p_browse_data[8];
+        BE_STREAM_TO_UINT32(cmd->get_items.end_item,end_item);
+        BTIF_TRACE_EVENT("pbrowse_msg start_item :%x",cmd->get_items.end_item);
+        cmd->get_items.attr_count = 0xff; /* in MediaPlayerList we don't have attr_id */
+        //Update OPCODE
+        cmd->get_items.opcode  = AVRC_OP_BROWSE;
+        cmd->get_items.scope   = pbrowse_msg->p_msg->browse.p_browse_data[3] ;
+        cmd->get_items.status = AVRC_STS_NO_ERROR ;
+        for (xx = 0; xx < MAX_ELEM_ATTR_SIZE ; xx++)
+        {
+            cmd->get_items.attrs[xx] = 0;
+        }
+        return FALSE;
+    }
+}
+
+/************************************************************************************
+*  Function                 handle_get_folder_item_filesystem_cmd
+*
+* - Argument:               tBTA_AV_BROWSE_MSG  structure containing  the received
+*                           browse message
+*                           tAVRC_COMMAND       structure containing the commands
+*                           to be updated
+*                           UINT8 event,        variable having value of event.
+*
+*  - Description:           Handler for get folder item command
+*
+************************************************************************************/
+UINT8 handle_get_folder_item_filesystem_cmd (tBTA_AV_BROWSE_MSG *pbrowse_msg, tAVRC_COMMAND *cmd,
+                                                 UINT8 *event)
+{
+    UINT8 *p_length, *start_item, *end_item, *p_data;
+    UINT8 length, attr_count = 0, xx;
+    *event = pbrowse_msg->p_msg->browse.p_browse_data[0] ;
+    cmd->get_items.pdu = *event;
+    //Check length
+    p_length = &pbrowse_msg->p_msg->browse.p_browse_data[1];
+    BE_STREAM_TO_UINT16(length, p_length);
+    attr_count = pbrowse_msg->p_msg->browse.p_browse_data[12];
+    BTIF_TRACE_ERROR("GET_FOLDER_ITEMS: attr_count: =%d", attr_count);
+    switch (attr_count)
+    {
+        case 0xff:
+            if (length != 10)
+            {
+                BTIF_TRACE_ERROR("GET_FOLDER_ITEMS: length error: =%d", length);
+                return TRUE;
+            }
+            break;
+        default:
+            if (length != ((attr_count * 4) + 10))
+            {
+                BTIF_TRACE_ERROR("GET_FOLDER_ITEMS: length error: =%d", length);
+                return TRUE;
+            }
+    }
+
+    start_item = &pbrowse_msg->p_msg->browse.p_browse_data[4];
+    BE_STREAM_TO_UINT32(cmd->get_items.start_item ,start_item);
+    BTIF_TRACE_EVENT("pbrowse_msg start_item :%x",cmd->get_items.start_item);
+    end_item  =  &pbrowse_msg->p_msg->browse.p_browse_data[8];
+    BE_STREAM_TO_UINT32(cmd->get_items.end_item,end_item);
+    BTIF_TRACE_EVENT("pbrowse_msg start_item :%x",cmd->get_items.end_item);
+    cmd->get_items.attr_count = attr_count;
+    if (attr_count == 0)
+    {
+        for (xx = 0; xx < MAX_ELEM_ATTR_SIZE; xx++)
+        {
+            cmd->get_items.attrs[xx] = xx + 1;
+        }
+    }
+    else if (attr_count == 0xff) /* no attribute requested */
+    {
+        BTIF_TRACE_DEBUG("No attribute requested");
+    }
+    else if (attr_count <= AVRC_MAX_ELEM_ATTR_SIZE)
+    {
+        p_data = &pbrowse_msg->p_msg->browse.p_browse_data[13];
+        for (xx = 0; xx < attr_count; xx++)
+            BE_STREAM_TO_UINT32(cmd->get_items.attrs[xx], p_data)
+    }
+    //Update OPCODE
+    cmd->get_items.opcode  = AVRC_OP_BROWSE;
+    cmd->get_items.scope   = pbrowse_msg->p_msg->browse.p_browse_data[3] ;
+    cmd->get_items.status = AVRC_STS_NO_ERROR ;
+    return FALSE;
+}
+
+/************************************************************************************
+*  Function                 handle_rc_browsemsg_cmd
+*
+* - Argument:               tBTA_AV_BROWSE_MSG  structure containing  the recieved
+*                           browse message
+*
+*  - Description:           Remote Control browse message handler
+*
+************************************************************************************/
+void handle_rc_browsemsg_cmd (tBTA_AV_BROWSE_MSG *pbrowse_msg)
+{
+    UINT8 event;
+    UINT16 length;
+    tAVRC_COMMAND cmd;
+    UINT8 *p_length, *p_data;
+    tAVRC_RESPONSE avrc_rsp;
+    UINT8  dropmsg = TRUE;
+    UINT8 index = btif_rc_get_idx_by_rc_handle(pbrowse_msg->rc_handle);
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: Invalid RC index", __FUNCTION__);
+        return;
+    }
+
+    BTIF_TRACE_EVENT("+ %s", __FUNCTION__);
+    BTIF_TRACE_EVENT("pbrowse_msg PDU_ID :%x",pbrowse_msg->p_msg->browse.p_browse_data[0]);
+    BTIF_TRACE_EVENT("pbrowse_msg length :%x",pbrowse_msg->p_msg->browse.browse_len);
+    switch(pbrowse_msg->p_msg->browse.p_browse_data[0])
+    {
+        case AVRC_PDU_GET_FOLDER_ITEMS:
+        {
+            UINT8 scope = pbrowse_msg->p_msg->browse.p_browse_data[3];
+            switch (scope)
+            {
+                case AVRC_SCOPE_PLAYER_LIST:
+                    dropmsg = handle_get_folder_item_mediaplyerlist_cmd(pbrowse_msg, &cmd, &event);
+                break;
+                case AVRC_SCOPE_FILE_SYSTEM:
+                case AVRC_SCOPE_NOW_PLAYING:
+                    dropmsg = handle_get_folder_item_filesystem_cmd(pbrowse_msg, &cmd, &event);
+                break;
+            }
+            if (dropmsg == FALSE)
+            {
+                btif_rc_upstreams_evt(event,&cmd,0,pbrowse_msg->label, index);
+            }
+        }
+        break;
+
+        case AVRC_PDU_SET_BROWSED_PLAYER:
+            event  = pbrowse_msg->p_msg->browse.p_browse_data[0] ;
+            cmd.br_player.pdu     = event;
+            //Check for length
+            p_length = &pbrowse_msg->p_msg->browse.p_browse_data[1];
+            BE_STREAM_TO_UINT16(length, p_length);
+            if (length != 0x0002)
+            {
+                BTIF_TRACE_ERROR("SET_BROWSED_PLAYERlength error: = %d", length);
+            }
+            else
+            {
+                p_length = &pbrowse_msg->p_msg->browse.p_browse_data[3];
+                BE_STREAM_TO_UINT16(cmd.br_player.player_id, p_length);
+                cmd.br_player.opcode = AVRC_OP_BROWSE;
+                btif_rc_upstreams_evt(event, &cmd, 0, pbrowse_msg->label, index);
+                dropmsg = FALSE;
+            }
+        break;
+
+        case AVRC_PDU_CHANGE_PATH:
+            event  = pbrowse_msg->p_msg->browse.p_browse_data[0] ;
+            cmd.chg_path.pdu = event;
+            p_data = &pbrowse_msg->p_msg->browse.p_browse_data[1];
+            BE_STREAM_TO_UINT16(length, p_data);
+            if (length != 11)
+            {
+                BTIF_TRACE_ERROR("CHANGE_PATH length error: = %d",length);
+            }
+            else
+            {
+                p_data = &pbrowse_msg->p_msg->browse.p_browse_data[3];
+                BE_STREAM_TO_UINT16(cmd.chg_path.uid_counter, p_data);
+                cmd.chg_path.direction = pbrowse_msg->p_msg->browse.p_browse_data[5];
+                cmd.chg_path.opcode = AVRC_OP_BROWSE;
+                cmd.chg_path.status = AVRC_STS_NO_ERROR;
+                p_data = &pbrowse_msg->p_msg->browse.p_browse_data[6];
+                BE_STREAM_TO_UINT64(cmd.chg_path.folder_uid, p_data);
+                btif_rc_upstreams_evt(event, &cmd, 0, pbrowse_msg->label, index);
+                dropmsg = FALSE;
+            }
+        break;
+
+        case AVRC_PDU_GET_ITEM_ATTRIBUTES:
+        {
+            UINT16 packet_len;
+            UINT8  num_attr, idx;
+            event  = pbrowse_msg->p_msg->browse.p_browse_data[0] ;
+            cmd.get_attrs.pdu = event;
+            p_data = &pbrowse_msg->p_msg->browse.p_browse_data[1];
+            BE_STREAM_TO_UINT16(packet_len, p_data);
+            p_data = &pbrowse_msg->p_msg->browse.p_browse_data[14];
+            BE_STREAM_TO_UINT8(num_attr, p_data);
+            if (packet_len != ((num_attr * 4) + 12))
+            {
+                BTIF_TRACE_ERROR("Get Item Attributes length error: = %d",packet_len);
+            }
+            else
+            {
+                cmd.get_attrs.status = AVRC_STS_NO_ERROR;
+                cmd.get_attrs.opcode = AVRC_OP_BROWSE;
+                cmd.get_attrs.scope =  pbrowse_msg->p_msg->browse.p_browse_data[3];
+                p_data = &pbrowse_msg->p_msg->browse.p_browse_data[4];
+                BE_STREAM_TO_UINT64(cmd.get_attrs.uid, p_data);
+                p_data = &pbrowse_msg->p_msg->browse.p_browse_data[12];
+                BE_STREAM_TO_UINT16(cmd.get_attrs.uid_counter, p_data);
+                cmd.get_attrs.attr_count = num_attr;
+                if (num_attr == 0)
+                {
+                    /* remote requested all Attribute ID*/
+                    for (idx = 0; idx < MAX_ELEM_ATTR_SIZE; idx++)
+                    {
+                        cmd.get_attrs.attrs[idx] = idx + 1;
+                    }
+                }
+                else
+                {
+                    p_data = &pbrowse_msg->p_msg->browse.p_browse_data[15];
+                    BTIF_TRACE_ERROR("GetItemAttr num_attr: = %d", cmd.get_attrs.attr_count);
+                    for (idx = 0; idx < num_attr ; idx++)
+                    {
+                        BE_STREAM_TO_UINT32(cmd.get_attrs.attrs[idx], p_data);
+                        BTIF_TRACE_ERROR("GetItemAttr attrid: = %d", cmd.get_attrs.attrs[idx]);
+                    }
+                }
+                btif_rc_upstreams_evt(event, &cmd, 0, pbrowse_msg->label, index);
+                dropmsg = FALSE;
+            }
+        }
+        break;
+
+        case AVRC_PDU_GET_TOTAL_NUMBER_OF_ITEMS:
+           event = pbrowse_msg->p_msg->browse.p_browse_data[0];
+           cmd.get_tot_item.pdu = event;
+           p_data = &pbrowse_msg->p_msg->browse.p_browse_data[1];
+           BE_STREAM_TO_UINT16(length, p_data);
+           if (length != 1)
+           {
+               BTIF_TRACE_ERROR("GET_TOTAL_ITEMS length error: = %d", length);
+           }
+           else
+           {
+               p_data = &pbrowse_msg->p_msg->browse.p_browse_data[3];
+               BE_STREAM_TO_UINT8(cmd.get_tot_item.scope, p_data);
+               cmd.get_tot_item.opcode = AVRC_OP_BROWSE;
+               cmd.get_tot_item.status = AVRC_STS_NO_ERROR;
+               btif_rc_upstreams_evt(event, &cmd, 0, pbrowse_msg->label, index);
+               dropmsg = FALSE;
+           }
+        break;
+
+        default:
+            BTIF_TRACE_ERROR("pbrowse_msg ERROR");
+        break;
+    }
+    if (dropmsg == TRUE)
+    {
+        avrc_rsp.rsp.pdu    = pbrowse_msg->p_msg->browse.p_browse_data[0];
+        avrc_rsp.rsp.status = AVRC_STS_BAD_CMD;
+        avrc_rsp.rsp.opcode = AVRC_OP_BROWSE;
+        BTIF_TRACE_ERROR("handle_rc_browsemsg_cmd: pbrowse_msg ERROR: %x", avrc_rsp.rsp.pdu);
+        send_browsemsg_rsp(btif_rc_cb[index].rc_handle, pbrowse_msg->label, 0, &avrc_rsp);
+    }
+
+}
+
+
 /***************************************************************************
  **
  ** Function       btif_rc_handler
@@ -995,9 +1719,24 @@
  ***************************************************************************/
 void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data)
 {
-    BTIF_TRACE_DEBUG ("%s event:%s", __FUNCTION__, dump_rc_event(event));
+    UINT8 index;
+
+    BTIF_TRACE_IMP ("%s event:%s", __FUNCTION__, dump_rc_event(event));
     switch (event)
     {
+        case BTIF_AV_CLEANUP_REQ_EVT:
+        {
+            memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
+            close_uinput();
+
+            if (bt_rc_callbacks)
+            {
+                bt_rc_callbacks = NULL;
+            }
+
+            lbl_destroy();
+        }break;
+
         case BTA_AV_RC_OPEN_EVT:
         {
             BTIF_TRACE_DEBUG("%s Peer_features:%x", __FUNCTION__, p_data->rc_open.peer_features);
@@ -1011,28 +1750,13 @@
 
         case BTA_AV_REMOTE_CMD_EVT:
         {
-            if (bt_rc_callbacks != NULL)
-            {
-              BTIF_TRACE_DEBUG("%s rc_id:0x%x key_state:%d",
-                               __FUNCTION__, p_data->remote_cmd.rc_id,
+            BTIF_TRACE_DEBUG("rc_id:0x%x key_state:%d", p_data->remote_cmd.rc_id,
                                p_data->remote_cmd.key_state);
-                /** In race conditions just after 2nd AVRCP is connected
-                 *  remote might send pass through commands, so check for
-                 *  Rc handle before processing pass through commands
-                 **/
-                if (btif_rc_cb.rc_handle == p_data->remote_cmd.rc_handle)
-                {
-                    handle_rc_passthrough_cmd( (&p_data->remote_cmd) );
-                }
-                else
-                {
-                    BTIF_TRACE_DEBUG("%s Pass-through command for Invalid rc handle", __FUNCTION__);
-                }
-            }
-            else
-            {
-                BTIF_TRACE_ERROR("AVRCP TG role not up, drop passthrough commands");
-            }
+            /** In race conditions just after 2nd AVRCP is connected
+             *  remote might send pass through commands, so check for
+             *  Rc handle before processing pass through commands
+             **/
+            handle_rc_passthrough_cmd( (&p_data->remote_cmd) );
         }
         break;
 
@@ -1055,13 +1779,20 @@
 #endif
         case BTA_AV_RC_FEAT_EVT:
         {
-            BTIF_TRACE_DEBUG("%s Peer_features:%x", __FUNCTION__, p_data->rc_feat.peer_features);
-            btif_rc_cb.rc_features = p_data->rc_feat.peer_features;
-            handle_rc_features(p_data->rc_feat.peer_addr);
-#if (AVRC_CTLR_INCLUDED == TRUE)
-            if ((btif_rc_cb.rc_connected) && (bt_rc_ctrl_callbacks != NULL))
+            BTIF_TRACE_DEBUG("Peer_features:%x on RC handle: %d", p_data->rc_feat.peer_features,
+                            p_data->rc_feat.rc_handle);
+            index = btif_rc_get_idx_by_rc_handle(p_data->rc_feat.rc_handle);
+            if (index == btif_max_rc_clients)
             {
-                handle_rc_ctrl_features(btif_rc_cb.rc_addr);
+                BTIF_TRACE_ERROR("%s: Invalid RC index for BTA_AV_RC_FEAT_EVT", __FUNCTION__);
+                return;
+            }
+            btif_rc_cb[index].rc_features = p_data->rc_feat.peer_features;
+            handle_rc_features(index);
+#if (AVRC_CTLR_INCLUDED == TRUE)
+            if ((btif_rc_cb[index].rc_connected == TRUE) && (bt_rc_ctrl_callbacks != NULL))
+            {
+                handle_rc_ctrl_features(index);
             }
 #endif
         }
@@ -1114,10 +1845,17 @@
             else
             {
                 BTIF_TRACE_ERROR("Neither CTRL, nor TG is up, drop meta commands");
+                osi_free(p_data->meta_msg.p_msg);
             }
         }
         break;
-
+        case BTA_AV_BROWSE_MSG_EVT:
+        {
+            BTIF_TRACE_DEBUG("BTA_AV_BROWSE_MSG_EVT  label:%d handle:%d", p_data->browse_msg.label,
+                p_data->browse_msg.rc_handle);
+            handle_rc_browsemsg_cmd(&(p_data->browse_msg));
+        }
+        break;
         default:
             BTIF_TRACE_DEBUG("%s Unhandled RC event : 0x%x", __FUNCTION__, event);
     }
@@ -1132,13 +1870,37 @@
  ***************************************************************************/
 BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr)
 {
-    if (btif_rc_cb.rc_connected == TRUE) {
-        bdcpy(peer_addr, btif_rc_cb.rc_addr);
-        return TRUE;
+    /*Find the device for which AV is not connected but RC is.*/
+    int i;
+
+    for  (i = 0; i < btif_max_rc_clients; i++)
+    {
+        if (btif_rc_cb[i].rc_connected == TRUE)
+        {
+            if (!btif_av_is_device_connected(btif_rc_cb[i].rc_addr))
+            {
+                bdcpy(peer_addr, btif_rc_cb[i].rc_addr);
+                return TRUE;
+            }
+        }
     }
     return FALSE;
 }
 
+static int btif_rc_get_idx_by_addr(BD_ADDR address)
+{
+    int i;
+
+    for (i = 0; i < btif_max_rc_clients; i++)
+    {
+        if (bdcmp(btif_rc_cb[i].rc_addr, address) == 0)
+        {
+            break;
+        }
+    }
+    return i;
+}
+
 /***************************************************************************
  **
  ** Function       btif_rc_get_connected_peer_handle
@@ -1146,9 +1908,18 @@
  ** Description    Fetches the connected headset's handle if any
  **
  ***************************************************************************/
-UINT8 btif_rc_get_connected_peer_handle(void)
+UINT8 btif_rc_get_connected_peer_handle(BD_ADDR peer_addr)
 {
-    return btif_rc_cb.rc_handle;
+    int i;
+    for  (i = 0; i < btif_max_rc_clients; i++)
+    {
+        if ((btif_rc_cb[i].rc_connected == TRUE)
+             &&(!bdcmp(peer_addr,btif_rc_cb[i].rc_addr)))
+        {
+            return btif_rc_cb[i].rc_handle;
+        }
+    }
+    return BTIF_RC_HANDLE_NONE;
 }
 
 /***************************************************************************
@@ -1162,10 +1933,17 @@
 /* clear the queued PLAY command. if bSend is TRUE, forward to app */
 void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, BOOLEAN bSendToApp)
 {
+    int index = btif_rc_get_idx_by_addr(peer_addr);
+
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: Invalid RC index", __FUNCTION__);
+        return;
+    }
     UNUSED(peer_addr);
 
     BTIF_TRACE_DEBUG("%s: bSendToApp=%d", __FUNCTION__, bSendToApp);
-    if (btif_rc_cb.rc_pending_play)
+    if (btif_rc_cb[index].rc_pending_play)
     {
         if (bSendToApp)
         {
@@ -1173,7 +1951,7 @@
             APPL_TRACE_DEBUG("%s: Sending queued PLAYED event to app", __FUNCTION__);
 
             memset (&remote_cmd, 0, sizeof(tBTA_AV_REMOTE_CMD));
-            remote_cmd.rc_handle  = btif_rc_cb.rc_handle;
+            remote_cmd.rc_handle  = btif_rc_cb[index].rc_handle;
             remote_cmd.rc_id      = AVRC_ID_PLAY;
             remote_cmd.hdr.ctype  = AVRC_CMD_CTRL;
             remote_cmd.hdr.opcode = AVRC_OP_PASS_THRU;
@@ -1192,7 +1970,7 @@
             remote_cmd.key_state  = AVRC_STATE_RELEASE;
             handle_rc_passthrough_cmd( &remote_cmd );
         }
-        btif_rc_cb.rc_pending_play = FALSE;
+        btif_rc_cb[index].rc_pending_play = FALSE;
     }
 }
 
@@ -1232,7 +2010,14 @@
     tAVRC_RESPONSE *pmetamsg_resp)
 {
     UINT8 ctype;
+    UINT8 index;
 
+    index = btif_rc_get_idx_by_rc_handle(rc_handle);
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: Invalid RC index", __FUNCTION__);
+        return;
+    }
     if (!pmetamsg_resp)
     {
         BTIF_TRACE_WARNING("%s: Invalid response received from application", __FUNCTION__);
@@ -1274,24 +2059,24 @@
     {
         BOOLEAN bSent = FALSE;
         UINT8   event_id = pmetamsg_resp->reg_notif.event_id;
-        BOOLEAN bNotify = (btif_rc_cb.rc_connected) && (btif_rc_cb.rc_notif[event_id-1].bNotify);
+        BOOLEAN bNotify = (btif_rc_cb[index].rc_connected) && (btif_rc_cb[index].rc_notif[event_id-1].bNotify);
 
         /* de-register this notification for a CHANGED response */
-        btif_rc_cb.rc_notif[event_id-1].bNotify = FALSE;
+        btif_rc_cb[index].rc_notif[event_id-1].bNotify = FALSE;
         BTIF_TRACE_DEBUG("%s rc_handle: %d. event_id: 0x%02d bNotify:%u", __FUNCTION__,
-             btif_rc_cb.rc_handle, event_id, bNotify);
+             btif_rc_cb[index].rc_handle, event_id, bNotify);
         if (bNotify)
         {
             BT_HDR *p_msg = NULL;
             tAVRC_STS status;
 
-            if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(btif_rc_cb.rc_handle,
+            if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(btif_rc_cb[index].rc_handle,
                 pmetamsg_resp, &p_msg)) )
             {
                 BTIF_TRACE_DEBUG("%s Sending notification to rc_handle: %d. event_id: 0x%02d",
-                     __FUNCTION__, btif_rc_cb.rc_handle, event_id);
+                     __FUNCTION__, btif_rc_cb[index].rc_handle, event_id);
                 bSent = TRUE;
-                BTA_AvMetaRsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
+                BTA_AvMetaRsp(btif_rc_cb[index].rc_handle, btif_rc_cb[index].rc_notif[event_id-1].label,
                     ctype, p_msg);
             }
             else
@@ -1348,6 +2133,68 @@
     return opcode;
 }
 
+/****************************************************************************
+* Function         send_browsemsg_rsp
+*
+* Arguments    -   rc_handle     RC handle corresponding to the connected RC
+*                  label         Label of the RC response
+*                  code          Response type---->Not needed for Browsing
+*                  pmetamsg_resp Vendor response
+*
+* Description  -   Remote control browse Message Rsp
+*
+*******************************************************************************/
+static void send_browsemsg_rsp (UINT8 rc_handle, UINT8 label, tBTA_AV_CODE code,
+                                                       tAVRC_RESPONSE *pbrowsemsg_resp)
+{
+    tAVRC_STS status;
+    BT_HDR *p_msg = NULL;
+
+    if (!pbrowsemsg_resp)
+    {
+        BTIF_TRACE_WARNING("%s: Invalid response received from application", __FUNCTION__);
+        return;
+    }
+
+    BTIF_TRACE_EVENT("+%s:rc_handle: %d, label: %d, code: 0x%02x, pdu: %s", __FUNCTION__,\
+                      rc_handle, label, code, dump_rc_pdu(pbrowsemsg_resp->rsp.pdu));
+    if (pbrowsemsg_resp->rsp.status != AVRC_STS_NO_ERROR)
+    {
+        BTIF_TRACE_ERROR("send_browsemsg_rsp **Error**");
+    }
+    /*Browse Command and Response structure are different
+     *as comapared to Meta data response ,opcode and c-type
+     *not part of browse response hence handling browse response
+     *in seprate function
+    */
+    status = AVRC_BldBrowseResponse(rc_handle, pbrowsemsg_resp, &p_msg);
+    if (status == AVRC_STS_NO_ERROR)
+    {
+        BTA_AvMetaRsp(rc_handle, label, 0, p_msg);
+    }
+    else
+    {
+        BTIF_TRACE_ERROR("%s: failed to build metamsg response. status: 0x%02x",
+                __FUNCTION__, status);
+    }
+}
+
+/****************************************************************************
+* Function         app_sendbrowsemsg
+*
+* Arguments    -   index         Of array stored while recieving command
+*                  avrc_rsp      Avrcp response from application
+*
+* Description  -   Send Browse message
+*
+*******************************************************************************/
+int app_sendbrowsemsg(UINT8 index ,tAVRC_RESPONSE *avrc_rsp, int rc_index)
+{
+   SEND_BROWSEMSG_RSP(index ,avrc_rsp, rc_index);
+   return 0;
+}
+
+
 /*******************************************************************************
 **
 ** Function         btif_rc_upstreams_evt
@@ -1357,41 +2204,169 @@
 ** Returns          void
 **
 *******************************************************************************/
-static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 ctype, UINT8 label)
+static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 ctype, UINT8 label,
+                                int index)
 {
-    BTIF_TRACE_EVENT("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
-        dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle, ctype, label);
+    bt_bdaddr_t remote_addr;
+    BD_ADDR address;
 
+    bdcpy(remote_addr.address, btif_rc_cb[index].rc_addr);
+    BTIF_TRACE_IMP("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
+        dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb[index].rc_handle, ctype, label);
+
+    if (interop_match_addr(INTEROP_DISABLE_PLAYER_APPLICATION_SETTING_CMDS,
+            (bt_bdaddr_t *) &remote_addr))
+    {
+        if (event == AVRC_PDU_LIST_PLAYER_APP_ATTR || event == AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT ||
+            event == AVRC_PDU_GET_CUR_PLAYER_APP_VALUE || event == AVRC_PDU_SET_PLAYER_APP_VALUE ||
+            event == AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT || event == AVRC_PDU_LIST_PLAYER_APP_VALUES)
+        {
+            send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu,
+                                AVRC_STS_BAD_PARAM);
+            BTIF_TRACE_DEBUG("Blacklisted CK send AVRC_PDU_LIST_PLAYER_APP_ATTR reject");
+            return;
+        }
+        if ((pavrc_cmd->reg_notif.event_id == BTRC_EVT_APP_SETTINGS_CHANGED) &&
+                (event == AVRC_PDU_REGISTER_NOTIFICATION))
+        {
+            send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu,
+                                AVRC_STS_BAD_PARAM);
+            btif_rc_cb[index].rc_notif[BTRC_EVT_APP_SETTINGS_CHANGED - 1].bNotify = FALSE;
+            BTIF_TRACE_DEBUG("Blacklisted CK send BTRC_EVT_APP_SETTINGS_CHANGED not implemented");
+            return;
+        }
+    }
     switch (event)
     {
         case AVRC_PDU_GET_PLAY_STATUS:
         {
-            FILL_PDU_QUEUE(IDX_GET_PLAY_STATUS_RSP, ctype, label, TRUE)
-            HAL_CBACK(bt_rc_callbacks, get_play_status_cb);
+            BTIF_TRACE_DEBUG("AVRC_PDU_GET_PLAY_STATUS ");
+            FILL_PDU_QUEUE(IDX_GET_PLAY_STATUS_RSP, ctype, label, TRUE, index, pavrc_cmd->pdu)
+            HAL_CBACK(bt_rc_callbacks, get_play_status_cb, &remote_addr);
         }
         break;
         case AVRC_PDU_LIST_PLAYER_APP_ATTR:
+        {
+            BTIF_TRACE_DEBUG("AVRC_PDU_LIST_PLAYER_APP_ATTR ");
+            FILL_PDU_QUEUE(IDX_LIST_APP_ATTR_RSP, ctype, label, TRUE, index, pavrc_cmd->pdu)
+            HAL_CBACK(bt_rc_callbacks, list_player_app_attr_cb, &remote_addr);
+        }
+        break;
         case AVRC_PDU_LIST_PLAYER_APP_VALUES:
+        {
+            BTIF_TRACE_DEBUG("AVRC_PDU_LIST_PLAYER_APP_VALUES =%d" ,pavrc_cmd->list_app_values.attr_id);
+            if (pavrc_cmd->list_app_values.attr_id == 0)
+            {
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu,
+                                    AVRC_STS_BAD_PARAM);
+                break;
+            }
+            FILL_PDU_QUEUE(IDX_LIST_APP_VALUE_RSP, ctype, label, TRUE, index, pavrc_cmd->pdu)
+            HAL_CBACK(bt_rc_callbacks, list_player_app_values_cb,
+                    pavrc_cmd->list_app_values.attr_id,
+                    &remote_addr);
+        }
+        break;
         case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
+        {
+            btrc_player_attr_t player_attr[MAX_ELEM_ATTR_SIZE];
+            UINT8 player_attr_num;
+            BTIF_TRACE_DEBUG("PLAYER_APP_VALUE PDU 0x13 = %d",pavrc_cmd->get_cur_app_val.num_attr);
+            if ((pavrc_cmd->get_cur_app_val.num_attr == 0) ||
+                  (pavrc_cmd->get_cur_app_val.num_attr > MAX_ELEM_ATTR_SIZE))
+            {
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu,
+                                    AVRC_STS_BAD_PARAM);
+                break;
+            }
+            memset( player_attr, 0, sizeof(player_attr));
+            for (player_attr_num = 0 ; player_attr_num < pavrc_cmd->get_cur_app_val.num_attr;
+                                                                            ++player_attr_num)
+            {
+                player_attr[player_attr_num] = pavrc_cmd->get_cur_app_val.attrs[player_attr_num];
+            }
+            FILL_PDU_QUEUE(IDX_GET_CURR_APP_VAL_RSP, ctype, label, TRUE, index, pavrc_cmd->pdu)
+            HAL_CBACK(bt_rc_callbacks, get_player_app_value_cb ,
+                    pavrc_cmd->get_cur_app_val.num_attr, player_attr, &remote_addr);
+        }
+        break;
         case AVRC_PDU_SET_PLAYER_APP_VALUE:
+        {
+            btrc_player_settings_t attr;
+            UINT8 count;
+            if ((pavrc_cmd->set_app_val.num_val== 0) ||
+                              (pavrc_cmd->set_app_val.num_val > MAX_ELEM_ATTR_SIZE))
+            {
+                send_reject_response (btif_rc_cb[index].rc_handle, label,
+                                       pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
+                break;
+            }
+            else
+            {
+                for(count = 0; count < pavrc_cmd->set_app_val.num_val ; ++count)
+                {
+                    attr.attr_ids[count] = pavrc_cmd->set_app_val.p_vals[count].attr_id ;
+                    attr.attr_values[count]= pavrc_cmd->set_app_val.p_vals[count].attr_val;
+                }
+                attr.num_attr  =  pavrc_cmd->set_app_val.num_val ;
+                FILL_PDU_QUEUE(IDX_SET_APP_VAL_RSP, ctype, label, TRUE, index, pavrc_cmd->pdu)
+                HAL_CBACK(bt_rc_callbacks, set_player_app_value_cb, &attr, &remote_addr);
+            }
+        }
+        break;
         case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
+        {
+            btrc_player_attr_t player_attr_txt [MAX_ELEM_ATTR_SIZE];
+            UINT8 count_txt = 0 ;
+            if ((pavrc_cmd->get_app_attr_txt.num_attr == 0) ||
+                   (pavrc_cmd->get_app_attr_txt.num_attr > MAX_ELEM_ATTR_SIZE))
+            {
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
+            }
+            else
+            {
+                for (count_txt = 0;count_txt < pavrc_cmd->get_app_attr_txt.num_attr ; ++count_txt)
+                {
+                    player_attr_txt[count_txt] = pavrc_cmd->get_app_attr_txt.attrs[count_txt];
+                }
+                FILL_PDU_QUEUE(IDX_GET_APP_ATTR_TXT_RSP, ctype, label, TRUE, index, pavrc_cmd->pdu)
+                HAL_CBACK(bt_rc_callbacks, get_player_app_attrs_text_cb,
+                            pavrc_cmd->get_app_attr_txt.num_attr, player_attr_txt, &remote_addr);
+            }
+        }
+        break;
         case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
         {
-            /* TODO: Add support for Application Settings */
-            send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_CMD);
+            if (pavrc_cmd->get_app_val_txt.attr_id == 0 ||
+                     pavrc_cmd->get_app_val_txt.attr_id > AVRC_PLAYER_VAL_GROUP_REPEAT)
+            {
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
+                break;
+            }
+            if (pavrc_cmd->get_app_val_txt.num_val == 0)
+            {
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
+            }
+            else
+            {
+                FILL_PDU_QUEUE(IDX_GET_APP_VAL_TXT_RSP, ctype, label, TRUE, index, pavrc_cmd->pdu)
+                HAL_CBACK(bt_rc_callbacks, get_player_app_values_text_cb,
+                          pavrc_cmd->get_app_val_txt.attr_id, pavrc_cmd->get_app_val_txt.num_val,
+                          pavrc_cmd->get_app_val_txt.vals, &remote_addr);
+            }
         }
         break;
         case AVRC_PDU_GET_ELEMENT_ATTR:
         {
-            btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
+            btrc_media_attr_t element_attrs[MAX_ELEM_ATTR_SIZE];
             UINT8 num_attr;
-             memset(&element_attrs, 0, sizeof(element_attrs));
+            memset(&element_attrs, 0, sizeof(element_attrs));
             if (pavrc_cmd->get_elem_attrs.num_attr == 0)
             {
                 /* CT requests for all attributes */
                 int attr_cnt;
-                num_attr = BTRC_MAX_ELEM_ATTR_SIZE;
-                for (attr_cnt = 0; attr_cnt < BTRC_MAX_ELEM_ATTR_SIZE; attr_cnt++)
+                num_attr = MAX_ELEM_ATTR_SIZE;
+                for (attr_cnt = 0; attr_cnt < MAX_ELEM_ATTR_SIZE; attr_cnt++)
                 {
                     element_attrs[attr_cnt] = attr_cnt + 1;
                 }
@@ -1399,7 +2374,7 @@
             else if (pavrc_cmd->get_elem_attrs.num_attr == 0xFF)
             {
                 /* 0xff indicates, no attributes requested - reject */
-                send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu,
                     AVRC_STS_BAD_PARAM);
                 return;
             }
@@ -1433,8 +2408,19 @@
                     }
                 }
             }
-            FILL_PDU_QUEUE(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, TRUE);
-            HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs);
+#if (defined(AVCT_COVER_ART_INCLUDED) && (AVCT_COVER_ART_INCLUDED == TRUE))
+            int ver = AVRC_REV_INVALID;
+            ver = sdp_get_stored_avrc_tg_version (remote_addr.address);
+            if ((!(btif_rc_cb[index].rc_features & BTA_AV_FEAT_CA)) ||
+                  (ver < AVRC_REV_1_6) || (ver == AVRC_REV_INVALID))
+            {
+                BTIF_TRACE_IMP("remove the cover art elem attribute if remote doesn't support avrcp1.6");
+                if(num_attr == MAX_ELEM_ATTR_SIZE)
+                    num_attr--;
+            }
+#endif
+            FILL_PDU_QUEUE(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, TRUE, index, pavrc_cmd->pdu);
+            HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs, &remote_addr);
         }
         break;
         case AVRC_PDU_REGISTER_NOTIFICATION:
@@ -1444,34 +2430,227 @@
             {
                 BTIF_TRACE_WARNING("%s Device registering position changed with illegal param 0.",
                     __FUNCTION__);
-                send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
                 /* de-register this notification for a rejected response */
-                btif_rc_cb.rc_notif[BTRC_EVT_PLAY_POS_CHANGED - 1].bNotify = FALSE;
+                btif_rc_cb[index].rc_notif[BTRC_EVT_PLAY_POS_CHANGED - 1].bNotify = FALSE;
                 return;
             }
             HAL_CBACK(bt_rc_callbacks, register_notification_cb, pavrc_cmd->reg_notif.event_id,
-                pavrc_cmd->reg_notif.param);
+                pavrc_cmd->reg_notif.param, &remote_addr);
         }
         break;
         case AVRC_PDU_INFORM_DISPLAY_CHARSET:
         {
             tAVRC_RESPONSE avrc_rsp;
             BTIF_TRACE_EVENT("%s() AVRC_PDU_INFORM_DISPLAY_CHARSET", __FUNCTION__);
-            if (btif_rc_cb.rc_connected == TRUE)
+            if(btif_rc_cb[index].rc_connected == TRUE)
             {
                 memset(&(avrc_rsp.inform_charset), 0, sizeof(tAVRC_RSP));
                 avrc_rsp.inform_charset.opcode=opcode_from_pdu(AVRC_PDU_INFORM_DISPLAY_CHARSET);
                 avrc_rsp.inform_charset.pdu=AVRC_PDU_INFORM_DISPLAY_CHARSET;
                 avrc_rsp.inform_charset.status=AVRC_STS_NO_ERROR;
-                send_metamsg_rsp(btif_rc_cb.rc_handle, label, ctype, &avrc_rsp);
+                send_metamsg_rsp(btif_rc_cb[index].rc_handle, label, ctype, &avrc_rsp);
+            }
+        }
+        break;
+        case AVRC_PDU_SET_ADDRESSED_PLAYER:
+        {
+            BTIF_TRACE_EVENT("%s() AVRC_PDU_SET_ADDRESSED_PLAYER", __FUNCTION__);
+            FILL_PDU_QUEUE(IDX_SET_ADDRESS_PLAYER_RSP, ctype, label, TRUE, index, pavrc_cmd->pdu);
+            if (!btif_hf_is_call_vr_idle())
+            {
+                set_addrplayer_rsp(ERR_PLAYER_NOT_ADDRESED, &remote_addr); // send reject if call is in progress
+                return;
+            }
+            if (btif_rc_cb[index].rc_connected == TRUE)
+            {
+                HAL_CBACK(bt_rc_callbacks, set_addrplayer_cb, pavrc_cmd->addr_player.player_id, &remote_addr);
+            }
+        }
+        break;
+        case AVRC_PDU_GET_FOLDER_ITEMS:
+        {
+            btrc_getfolderitem_t getfolder;
+            btrc_browse_folderitem_t scope;
+            UINT8  idx, numAttr;
+            BTIF_TRACE_EVENT("%s()AVRC_PDU_GET_FOLDER_ITEMS", __FUNCTION__);
+            FILL_PDU_QUEUE(IDX_GET_FOLDER_ITEMS_RSP,ctype, label, TRUE, index, pavrc_cmd->pdu);
+            BTIF_TRACE_EVENT("rc_connected: %d",btif_rc_cb[index].rc_connected);
+            if (btif_rc_cb[index].rc_connected == TRUE)
+            {
+                getfolder.start_item = pavrc_cmd->get_items.start_item;
+                getfolder.end_item   = pavrc_cmd->get_items.end_item;
+                getfolder.size       = AVCT_GetBrowseMtu(btif_rc_cb[index].rc_handle);
+                getfolder.attr_count = pavrc_cmd->get_items.attr_count;
+                scope                = (btrc_browse_folderitem_t)pavrc_cmd->get_items.scope;
+                if (getfolder.attr_count == 255)
+                {
+                    numAttr = 0;
+                }
+                else
+                {
+                    if (getfolder.attr_count == 0)
+                    {
+                        numAttr = MAX_ELEM_ATTR_SIZE;
+                        for (idx = 0; idx < MAX_ELEM_ATTR_SIZE; idx++)
+                        {
+                            getfolder.attrs[idx] = idx + 1;
+                        }
+                    }
+                    else
+                    {
+                        numAttr = getfolder.attr_count;
+                        for (idx = 0; idx < numAttr; idx++)
+                        {
+                            getfolder.attrs[idx] = pavrc_cmd->get_items.attrs[idx];
+                            BTIF_TRACE_ERROR("getfolder[%d] = %d", idx, getfolder.\
+                                                                        attrs[idx]);
+                            BTIF_TRACE_ERROR("pavrc_cmd->get_items.attrs[%d] = %d",\
+                                            idx, pavrc_cmd->get_items.attrs[idx]);
+                        }
+                    }
+                }
+                HAL_CBACK(bt_rc_callbacks, get_folderitems_cb, scope, &getfolder, &remote_addr);
+            }
+        }
+        break;
+        case AVRC_PDU_SET_BROWSED_PLAYER:
+        {
+            BTIF_TRACE_EVENT("%s() AVRC_PDU_SET_BROWSED_PLAYER", __FUNCTION__);
+            if (btif_rc_cb[index].rc_connected == TRUE)
+            {
+                FILL_PDU_QUEUE(IDX_SET_BROWSE_PLAYER_RSP, ctype, label, TRUE, index,
+                        pavrc_cmd->pdu);
+                HAL_CBACK(bt_rc_callbacks, set_browsed_player_cb, pavrc_cmd->br_player.player_id, &remote_addr);
+            }
+        }
+        break;
+        case AVRC_PDU_CHANGE_PATH:
+        {
+            BTIF_TRACE_EVENT("%s() AVRC_PDU_CHANGE_PATH", __FUNCTION__);
+            if (btif_rc_cb[index].rc_connected == TRUE)
+            {
+                FILL_PDU_QUEUE(IDX_CHANGE_PATH_RSP, ctype, label, TRUE, index, pavrc_cmd->pdu);
+                HAL_CBACK(bt_rc_callbacks, change_path_cb, pavrc_cmd->chg_path.direction, \
+                                                            pavrc_cmd->chg_path.folder_uid, &remote_addr);
+            }
+        }
+        break;
+        case AVRC_PDU_GET_ITEM_ATTRIBUTES:
+        {
+            UINT8 num_attr =  pavrc_cmd->get_attrs.attr_count;
+            UINT8 idx, num_attr_requested = 0;
+            BTIF_TRACE_EVENT("%s() AVRC_PDU_GET_ITEM_ATTRIBUTES", __FUNCTION__);
+            btrc_media_attr_t element_attrs[MAX_ELEM_ATTR_SIZE];
+            memset(&element_attrs, 0, sizeof(element_attrs));
+            if (num_attr == 0)
+            {
+                /* CT requests for all attributes */
+                for (idx = 0; idx < MAX_ELEM_ATTR_SIZE; idx++)
+                {
+                    element_attrs[idx] = idx + 1;
+                }
+                num_attr_requested = MAX_ELEM_ATTR_SIZE; /* get all */
+            }
+            else if (num_attr == 0xFF)
+            {
+                /* 0xff indicates, no attributes requested - reject */
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu,
+                    AVRC_STS_BAD_PARAM);
+                return;
+            }
+            else
+            {
+                /* Attribute IDs from 1 to MAX_ELEM_ATTR_SIZE are only valid,
+                 * hence HAL definition limits the attributes to BTRC_MAX_ELEM_ATTR_SIZE.
+                 * Fill only valid entries.
+                 */
+                for (idx = 0; (idx < num_attr) && (num_attr <= MAX_ELEM_ATTR_SIZE); idx++)
+                {
+                    if ((pavrc_cmd->get_attrs.attrs[idx] > 0) &&
+                        (pavrc_cmd->get_attrs.attrs[idx] <= MAX_ELEM_ATTR_SIZE))
+                    {
+                        element_attrs[idx] = pavrc_cmd->get_attrs.attrs[idx];
+                        BTIF_TRACE_ERROR("element_attrs[%d]: %d", idx, element_attrs[idx]);
+                    }
+                }
+                num_attr_requested = idx;
+                BTIF_TRACE_ERROR("num_attr_requested: %d", num_attr_requested);
+            }
+#if (defined(AVCT_COVER_ART_INCLUDED) && (AVCT_COVER_ART_INCLUDED == TRUE))
+            int ver = AVRC_REV_INVALID;
+            ver = sdp_get_stored_avrc_tg_version (remote_addr.address);
+            if ((!(btif_rc_cb[index].rc_features & BTA_AV_FEAT_CA)) ||
+                  (ver < AVRC_REV_1_6) || (ver == AVRC_REV_INVALID))
+            {
+                BTIF_TRACE_IMP("remove the cover art elem attribute if remote doesn't support avrcp1.6");
+                if(num_attr_requested == MAX_ELEM_ATTR_SIZE)
+                    num_attr_requested--;
+            }
+#endif
+            if (btif_rc_cb[index].rc_connected == TRUE)
+            {
+                FILL_PDU_QUEUE(IDX_GET_ITEM_ATTR_RSP, ctype, label, TRUE, index, pavrc_cmd->pdu);
+                HAL_CBACK(bt_rc_callbacks, get_item_attr_cb, pavrc_cmd->get_attrs.scope,
+                        pavrc_cmd->get_attrs.uid, num_attr_requested, element_attrs,
+                        AVCT_GetBrowseMtu(btif_rc_cb[index].rc_handle), &remote_addr);
+            }
+        }
+        break;
+        case AVRC_PDU_PLAY_ITEM:
+        {
+            BTIF_TRACE_EVENT("%s() AVRC_PDU_PLAY_ITEM", __FUNCTION__);
+            if (btif_rc_cb[index].rc_connected == TRUE)
+            {
+                FILL_PDU_QUEUE(IDX_PLAY_ITEM_RSP, ctype, label, TRUE, index, pavrc_cmd->pdu);
+                HAL_CBACK(bt_rc_callbacks, play_item_cb, pavrc_cmd->play_item.scope,
+                pavrc_cmd->play_item.uid, &remote_addr);
+                /*This command will trigger playback or
+                * dual a2dp handoff.. Let it play on this device. */
+                btif_rc_cb[index].rc_play_processed = TRUE;
+                /* Trigger DUAL Handoff when support single streaming */
+                if (btif_av_is_playing() &&
+                    (btif_av_get_multicast_state() == FALSE))
+                {
+                    //compare the bd addr of current playing dev and this dev
+                    btif_get_latest_playing_device(address);
+                    if (bdcmp(btif_rc_cb[index].rc_addr, address) == 0)
+                    {
+                        APPL_TRACE_WARNING("Play item on the playing device");
+                    } else
+                    {
+                        BTIF_TRACE_DEBUG("Play item on other device");
+                        if (btif_av_is_device_connected(btif_rc_cb[index].rc_addr))
+                        {
+                            //Trigger suspend on currently playing device
+                            BTIF_TRACE_DEBUG("Trigger dual handoff for this play Item command");
+                            btif_rc_cb[index].rc_play_processed = TRUE;
+                            btif_av_trigger_dual_handoff(TRUE, btif_rc_cb[index].rc_addr);
+                        } else
+                        {
+                            APPL_TRACE_WARNING("%s:Play item Invalid on %d", __FUNCTION__, index);
+                        }
+                    }
+                }
+            }
+        }
+        break;
+        case AVRC_PDU_GET_TOTAL_NUMBER_OF_ITEMS:
+        {
+            BTIF_TRACE_EVENT("%s() AVRC_PDU_GET_TOTAL_NUMBER_OF_ITEMS", __FUNCTION__);
+            if (btif_rc_cb[index].rc_connected == TRUE)
+            {
+                FILL_PDU_QUEUE(IDX_GET_TOTAL_ITEMS_RSP, ctype, label, TRUE, index, pavrc_cmd->pdu);
+                HAL_CBACK(bt_rc_callbacks, get_tot_item_cb, pavrc_cmd->get_tot_item.scope,
+                      &remote_addr);
             }
         }
         break;
         default:
         {
-        send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
-            (pavrc_cmd->pdu == AVRC_PDU_SEARCH)?AVRC_STS_SEARCH_NOT_SUP:AVRC_STS_BAD_CMD);
-        return;
+            send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu,
+                    (pavrc_cmd->pdu == AVRC_PDU_SEARCH)?AVRC_STS_SEARCH_NOT_SUP:
+                                                                    AVRC_STS_BAD_CMD);
         }
         break;
     }
@@ -1491,9 +2670,9 @@
         UINT8 label)
 {
     BTIF_TRACE_DEBUG("%s pdu: %s handle: 0x%x", __FUNCTION__,
-        dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle);
+        dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb[0].rc_handle);
     bt_bdaddr_t rc_addr;
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 #if (AVRC_CTLR_INCLUDED == TRUE)
     switch (event)
     {
@@ -1523,28 +2702,32 @@
 ** Returns          void
 **
 *******************************************************************************/
-static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label)
+static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label, int index)
 {
-    BTIF_TRACE_EVENT("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
-        dump_rc_pdu(pavrc_resp->pdu), btif_rc_cb.rc_handle, ctype, label);
+    bt_bdaddr_t remote_addr;
+
+    bdcpy(remote_addr.address, btif_rc_cb[index].rc_addr);
+    BTIF_TRACE_IMP("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
+        dump_rc_pdu(pavrc_resp->pdu), btif_rc_cb[index].rc_handle, ctype, label);
 
     switch (event)
     {
         case AVRC_PDU_REGISTER_NOTIFICATION:
         {
-             if (AVRC_RSP_CHANGED==ctype)
-                 btif_rc_cb.rc_volume=pavrc_resp->reg_notif.param.volume;
-             HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->reg_notif.param.volume,ctype)
+            if(AVRC_RSP_CHANGED==ctype)
+                 btif_rc_cb[index].rc_volume=pavrc_resp->reg_notif.param.volume;
+             HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->reg_notif.param.volume,ctype,
+                        &remote_addr)
         }
         break;
 
         case AVRC_PDU_SET_ABSOLUTE_VOLUME:
         {
-            BTIF_TRACE_DEBUG("%s Set absolute volume change event received: volume %d,ctype %d",
-                             __FUNCTION__, pavrc_resp->volume.volume,ctype);
-            if (AVRC_RSP_ACCEPT==ctype)
-                btif_rc_cb.rc_volume=pavrc_resp->volume.volume;
-            HAL_CBACK(bt_rc_callbacks,volume_change_cb,pavrc_resp->volume.volume,ctype)
+            BTIF_TRACE_DEBUG("Set absolute volume change event received: volume %d,ctype %d",
+                pavrc_resp->volume.volume,ctype);
+            if(AVRC_RSP_ACCEPT==ctype)
+                btif_rc_cb[index].rc_volume=pavrc_resp->volume.volume;
+            HAL_CBACK(bt_rc_callbacks,volume_change_cb,pavrc_resp->volume.volume,ctype, &remote_addr)
         }
         break;
 
@@ -1567,18 +2750,25 @@
 ** Returns          bt_status_t
 **
 *******************************************************************************/
-static bt_status_t init(btrc_callbacks_t* callbacks )
+//APP can pass the max conn value here too
+static bt_status_t init(btrc_callbacks_t* callbacks, int max_connections)
 {
-    BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
+    BTIF_TRACE_EVENT("## %s ##, max_connections = %d", __FUNCTION__, max_connections);
     bt_status_t result = BT_STATUS_SUCCESS;
+    int i;
 
     if (bt_rc_callbacks)
         return BT_STATUS_DONE;
 
     bt_rc_callbacks = callbacks;
+    btif_max_rc_clients = max_connections;
     memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
-    btif_rc_cb.rc_vol_label=MAX_LABEL;
-    btif_rc_cb.rc_volume=MAX_VOLUME;
+    for (i = 0; i < btif_max_rc_clients; i++)
+    {
+        btif_rc_cb[i].rc_vol_label=MAX_LABEL;
+        btif_rc_cb[i].rc_volume=MAX_VOLUME;
+        btif_rc_cb[i].rc_handle = BTIF_RC_HANDLE_NONE;
+    }
     lbl_init();
 
     return result;
@@ -1601,10 +2791,13 @@
     if (bt_rc_ctrl_callbacks)
         return BT_STATUS_DONE;
 
+    /* Controller is used only for Certification purposes.
+     * In normal case AVRCP controller will not be used, hence
+     * updating this is required.
+     */
     bt_rc_ctrl_callbacks = callbacks;
     memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
-    btif_rc_cb.rc_vol_label=MAX_LABEL;
-    btif_rc_cb.rc_volume=MAX_VOLUME;
+    btif_rc_cb[BTIF_RC_DEFAULT_INDEX].rc_vol_label=MAX_LABEL;
     lbl_init();
 
     return result;
@@ -1612,11 +2805,11 @@
 
 static void rc_ctrl_procedure_complete ()
 {
-    if (btif_rc_cb.rc_procedure_complete == TRUE)
+    if (btif_rc_cb[0].rc_procedure_complete == TRUE)
     {
         return;
     }
-    btif_rc_cb.rc_procedure_complete = TRUE;
+    btif_rc_cb[0].rc_procedure_complete = TRUE;
     UINT32 attr_list[] = {
             AVRC_MEDIA_ATTR_ID_TITLE,
             AVRC_MEDIA_ATTR_ID_ARTIST,
@@ -1626,7 +2819,9 @@
             AVRC_MEDIA_ATTR_ID_GENRE,
             AVRC_MEDIA_ATTR_ID_PLAYING_TIME
             };
-    get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
+    /* Fix for below Klowkwork Issue at line 2748
+     * Array 'attr_list' of size 7 may use index value(s) 7 */
+    get_element_attribute_cmd (sizeof(attr_list)/sizeof(UINT32), attr_list);
 }
 
 /***************************************************************************
@@ -1641,20 +2836,324 @@
 **
 ***************************************************************************/
 static bt_status_t get_play_status_rsp(btrc_play_status_t play_status, uint32_t song_len,
-    uint32_t song_pos)
+    uint32_t song_pos, bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
+    int rc_index;
+    int av_index;
     CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    av_index = btif_av_idx_by_bdaddr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("-%s on index = %d", __FUNCTION__, rc_index);
+
     memset(&(avrc_rsp.get_play_status), 0, sizeof(tAVRC_GET_PLAY_STATUS_RSP));
     avrc_rsp.get_play_status.song_len = song_len;
     avrc_rsp.get_play_status.song_pos = song_pos;
     avrc_rsp.get_play_status.play_status = play_status;
+    BTIF_TRACE_ERROR("%s: play_status: %d",__FUNCTION__, avrc_rsp.get_play_status.play_status);
+    if ((avrc_rsp.get_play_status.play_status == BTRC_PLAYSTATE_PLAYING) &&
+         (btif_av_check_flag_remote_suspend(av_index)))
+    {
+        BTIF_TRACE_ERROR("%s: clear remote suspend flag: %d",__FUNCTION__, av_index);
+        btif_av_clear_remote_suspend_flag();
+        if (btif_av_is_offload_supported())
+        {
+            btif_dispatch_sm_event(BTIF_AV_START_STREAM_REQ_EVT, NULL, 0);
+        }
+    }
 
     avrc_rsp.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
     avrc_rsp.get_play_status.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAY_STATUS);
     avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
     /* Send the response */
-    SEND_METAMSG_RSP(IDX_GET_PLAY_STATUS_RSP, &avrc_rsp);
+    SEND_METAMSG_RSP(IDX_GET_PLAY_STATUS_RSP, &avrc_rsp, rc_index);
+    return BT_STATUS_SUCCESS;
+}
+
+
+/**************************************************************************
+**
+** Function         list_player_app_attr_rsp
+**
+** Description      ListPlayerApplicationSettingAttributes (PDU ID: 0x11)
+**                  This method is callled in response to PDU 0x11
+**
+** Returns          bt_status_t
+**
+****************************************************************************/
+static bt_status_t  list_player_app_attr_rsp( uint8_t num_attr, btrc_player_attr_t *p_attrs, bt_bdaddr_t *bd_addr)
+{
+    tAVRC_RESPONSE avrc_rsp;
+    UINT32 i;
+    int rc_index;
+    CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("-%s on index = %d", __FUNCTION__, rc_index);
+
+    memset(&(avrc_rsp.list_app_attr), 0, sizeof(tAVRC_LIST_APP_ATTR_RSP));
+    if (num_attr == 0)
+    {
+        avrc_rsp.list_app_attr.status = AVRC_STS_BAD_PARAM;
+    }
+    else
+    {
+        avrc_rsp.list_app_attr.num_attr = num_attr;
+        for (i = 0 ; i < num_attr ; ++i)
+        {
+            avrc_rsp.list_app_attr.attrs[i] = p_attrs[i];
+        }
+        avrc_rsp.list_app_attr.status = AVRC_STS_NO_ERROR;
+    }
+    avrc_rsp.list_app_attr.pdu  = AVRC_PDU_LIST_PLAYER_APP_ATTR ;
+    avrc_rsp.list_app_attr.opcode = opcode_from_pdu(AVRC_PDU_LIST_PLAYER_APP_ATTR);
+    /* Send the response */
+    SEND_METAMSG_RSP(IDX_LIST_APP_ATTR_RSP, &avrc_rsp, rc_index);
+    return BT_STATUS_SUCCESS;
+}
+
+/**********************************************************************
+**
+** Function list_player_app_value_rsp
+**
+** Description      ListPlayerApplicationSettingValues (PDU ID: 0x12)
+                    This method is called in response to PDU 0x12
+************************************************************************/
+static bt_status_t  list_player_app_value_rsp( uint8_t num_val, uint8_t *value, bt_bdaddr_t *bd_addr)
+{
+    tAVRC_RESPONSE avrc_rsp;
+    UINT32 i;
+    int rc_index;
+    CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("-%s on index = %d", __FUNCTION__, rc_index);
+
+    memset(&(avrc_rsp.list_app_values), 0, sizeof(tAVRC_LIST_APP_VALUES_RSP));
+    if ((num_val == 0) || (num_val > AVRC_MAX_APP_ATTR_SIZE))
+    {
+        avrc_rsp.list_app_values.status = AVRC_STS_BAD_PARAM;
+    }
+    else
+    {
+        avrc_rsp.list_app_values.num_val = num_val;
+        for (i = 0; i < num_val; ++i)
+        {
+            avrc_rsp.list_app_values.vals[i] = value[i];
+        }
+        avrc_rsp.list_app_values.status = AVRC_STS_NO_ERROR;
+    }
+    avrc_rsp.list_app_values.pdu   = AVRC_PDU_LIST_PLAYER_APP_VALUES;
+    avrc_rsp.list_app_attr.opcode  = opcode_from_pdu(AVRC_PDU_LIST_PLAYER_APP_VALUES);
+    /* Send the response */
+    SEND_METAMSG_RSP(IDX_LIST_APP_VALUE_RSP, &avrc_rsp, rc_index);
+    return BT_STATUS_SUCCESS;
+}
+
+
+/**********************************************************************
+**
+** Function  get_player_app_value_rsp
+**
+** Description  This methos is called in response to PDU ID 0x13
+**
+***********************************************************************/
+static bt_status_t get_player_app_value_rsp(btrc_player_settings_t *p_vals, bt_bdaddr_t *bd_addr)
+{
+    tAVRC_RESPONSE avrc_rsp;
+    UINT32 i;
+    tAVRC_APP_SETTING app_sett[AVRC_MAX_APP_ATTR_SIZE];
+    int rc_index;
+    CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("-%s on index = %d", __FUNCTION__, rc_index);
+
+    memset(&(avrc_rsp.get_cur_app_val) ,0 , sizeof(tAVRC_GET_CUR_APP_VALUE_RSP));
+    avrc_rsp.get_cur_app_val.p_vals   = app_sett ;
+    //Check for Error Condition
+    if ((p_vals == NULL) || (p_vals->num_attr== 0) || (p_vals->num_attr > AVRC_MAX_APP_ATTR_SIZE))
+    {
+        avrc_rsp.get_cur_app_val.status = AVRC_STS_BAD_PARAM;
+    }
+    else if (p_vals->num_attr <= BTRC_MAX_APP_SETTINGS)
+    {
+        memset(app_sett, 0, sizeof(tAVRC_APP_SETTING)*p_vals->num_attr );
+        //update num_val
+        avrc_rsp.get_cur_app_val.num_val  = p_vals->num_attr ;
+        avrc_rsp.get_cur_app_val.p_vals   = app_sett ;
+        for (i = 0; i < p_vals->num_attr; ++i)
+        {
+            app_sett[i].attr_id  = p_vals->attr_ids[i] ;
+            app_sett[i].attr_val = p_vals->attr_values[i];
+            BTIF_TRACE_DEBUG("%s attr_id:0x%x, charset_id:0x%x, num_element:%d",
+                           __FUNCTION__, (unsigned int)app_sett[i].attr_id,
+                              app_sett[i].attr_val ,p_vals->num_attr );
+        }
+        //Update PDU , status aind
+        avrc_rsp.get_cur_app_val.status = AVRC_STS_NO_ERROR;
+    }
+    avrc_rsp.get_cur_app_val.pdu = AVRC_PDU_GET_CUR_PLAYER_APP_VALUE;
+    avrc_rsp.get_cur_app_val.opcode = opcode_from_pdu(AVRC_PDU_GET_CUR_PLAYER_APP_VALUE);
+    SEND_METAMSG_RSP(IDX_GET_CURR_APP_VAL_RSP, &avrc_rsp, rc_index);
+    return BT_STATUS_SUCCESS;
+}
+
+/********************************************************************
+**
+** Function     set_player_app_value_rsp
+**
+** Description  This method is called in response to
+**              application value
+**
+** Return       bt_staus_t
+**
+*******************************************************************/
+static bt_status_t set_player_app_value_rsp (btrc_status_t rsp_status, bt_bdaddr_t *bd_addr )
+{
+    tAVRC_RESPONSE avrc_rsp;
+    int rc_index;
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("-%s on index = %d", __FUNCTION__, rc_index);
+
+    CHECK_RC_CONNECTED
+    avrc_rsp.set_app_val.opcode = opcode_from_pdu(AVRC_PDU_SET_PLAYER_APP_VALUE);
+    avrc_rsp.set_app_val.pdu    =  AVRC_PDU_SET_PLAYER_APP_VALUE ;
+    avrc_rsp.set_app_val.status =  rsp_status ;
+    SEND_METAMSG_RSP(IDX_SET_APP_VAL_RSP, &avrc_rsp, rc_index);
+    return BT_STATUS_SUCCESS;
+}
+
+/********************************************************************
+**
+** Function      get_player_app_attr_text_rsp
+**
+** Description   This method is called in response to get player
+**               applicaton attribute text response
+**
+**
+*******************************************************************/
+static bt_status_t get_player_app_attr_text_rsp(int num_attr, btrc_player_setting_text_t *p_attrs,
+                                                bt_bdaddr_t *bd_addr)
+{
+    tAVRC_RESPONSE avrc_rsp;
+    tAVRC_APP_SETTING_TEXT attr_txt[AVRC_MAX_APP_ATTR_SIZE];
+    int i;
+    int rc_index;
+    CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("-%s on index = %d", __FUNCTION__, rc_index);
+
+    if (num_attr == 0)
+    {
+        avrc_rsp.get_app_attr_txt.status = AVRC_STS_BAD_PARAM;
+    }
+    else
+    {
+        for (i =0; i< num_attr; ++i)
+        {
+            attr_txt[i].charset_id = AVRC_CHARSET_ID_UTF8;
+            attr_txt[i].attr_id = p_attrs[i].id ;
+            attr_txt[i].str_len = (UINT8)strnlen((char *)p_attrs[i].text, BTRC_MAX_ATTR_STR_LEN);
+            attr_txt[i].p_str       = p_attrs[i].text ;
+            BTIF_TRACE_DEBUG("%s attr_id:0x%x, charset_id:0x%x, str_len:%d, str:%s",
+                                  __FUNCTION__, (unsigned int)attr_txt[i].attr_id,
+                                  attr_txt[i].charset_id , attr_txt[i].str_len, attr_txt[i].p_str);
+        }
+        avrc_rsp.get_app_attr_txt.status = AVRC_STS_NO_ERROR;
+    }
+    avrc_rsp.get_app_attr_txt.p_attrs = attr_txt ;
+    avrc_rsp.get_app_attr_txt.num_attr = (UINT8)num_attr;
+    avrc_rsp.get_app_attr_txt.pdu = AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT;
+    avrc_rsp.get_app_attr_txt.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT);
+    /* Send the response */
+    SEND_METAMSG_RSP(IDX_GET_APP_ATTR_TXT_RSP, &avrc_rsp, rc_index);
+    return BT_STATUS_SUCCESS;
+}
+
+/********************************************************************
+**
+** Function      get_player_app_value_text_rsp
+**
+** Description   This method is called in response to Player application
+**               value text
+**
+** Return        bt_status_t
+**
+*******************************************************************/
+static bt_status_t get_player_app_value_text_rsp(int num_attr, btrc_player_setting_text_t *p_attrs, bt_bdaddr_t *bd_addr)
+{
+    tAVRC_RESPONSE avrc_rsp;
+    tAVRC_APP_SETTING_TEXT attr_txt[AVRC_MAX_APP_ATTR_SIZE];
+    int i;
+    int rc_index;
+    CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
+
+    if (num_attr == 0)
+    {
+        avrc_rsp.get_app_val_txt.status = AVRC_STS_BAD_PARAM;
+    }
+    else
+    {
+        for (i =0; i< num_attr; ++i)
+        {
+            attr_txt[i].charset_id = AVRC_CHARSET_ID_UTF8;
+            attr_txt[i].attr_id  = p_attrs[i].id ;
+            attr_txt[i].str_len  = (UINT8)strnlen((char *)p_attrs[i].text ,BTRC_MAX_ATTR_STR_LEN );
+            attr_txt[i].p_str    = p_attrs[i].text ;
+            BTIF_TRACE_DEBUG("%s attr_id:0x%x, charset_id:0x%x, str_len:%d, str:%s",
+                                  __FUNCTION__, (unsigned int)attr_txt[i].attr_id,
+                                 attr_txt[i].charset_id , attr_txt[i].str_len,attr_txt[i].p_str);
+        }
+        avrc_rsp.get_app_val_txt.status = AVRC_STS_NO_ERROR;
+    }
+    avrc_rsp.get_app_val_txt.p_attrs = attr_txt;
+    avrc_rsp.get_app_val_txt.num_attr = (UINT8)num_attr;
+    avrc_rsp.get_app_val_txt.pdu = AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT;
+    avrc_rsp.get_app_val_txt.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT);
+    /* Send the response */
+    SEND_METAMSG_RSP(IDX_GET_APP_VAL_TXT_RSP, &avrc_rsp, rc_index);
     return BT_STATUS_SUCCESS;
 }
 
@@ -1663,34 +3162,45 @@
 ** Function         get_element_attr_rsp
 **
 ** Description      Returns the current songs' element attributes
-**                      in text.
+**                  in text.
 **
 ** Returns          bt_status_t
 **
 ***************************************************************************/
-static bt_status_t get_element_attr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p_attrs)
+static bt_status_t get_element_attr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p_attrs, bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
     UINT32 i;
-    tAVRC_ATTR_ENTRY element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
+    tAVRC_ATTR_ENTRY element_attrs[MAX_ELEM_ATTR_SIZE];
+    int rc_index;
     CHECK_RC_CONNECTED
-    memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
 
-    if (num_attr == 0)
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
+
+    if (num_attr == 0 || num_attr > MAX_ELEM_ATTR_SIZE)
     {
         avrc_rsp.get_play_status.status = AVRC_STS_BAD_PARAM;
     }
     else
     {
-        for (i=0; i<num_attr; i++) {
+        memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
+        for (i=0; i<num_attr; i++)
+        {
             element_attrs[i].attr_id = p_attrs[i].attr_id;
             element_attrs[i].name.charset_id = AVRC_CHARSET_ID_UTF8;
             element_attrs[i].name.str_len = (UINT16)strlen((char *)p_attrs[i].text);
             element_attrs[i].name.p_str = p_attrs[i].text;
             BTIF_TRACE_DEBUG("%s attr_id:0x%x, charset_id:0x%x, str_len:%d, str:%s",
-                             __FUNCTION__, (unsigned int)element_attrs[i].attr_id,
-                             element_attrs[i].name.charset_id, element_attrs[i].name.str_len,
-                             element_attrs[i].name.p_str);
+                __FUNCTION__, (unsigned int)element_attrs[i].attr_id,
+                element_attrs[i].name.charset_id,
+                element_attrs[i].name.str_len,
+                element_attrs[i].name.p_str);
         }
         avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
     }
@@ -1699,7 +3209,7 @@
     avrc_rsp.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
     avrc_rsp.get_elem_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ELEMENT_ATTR);
     /* Send the response */
-    SEND_METAMSG_RSP(IDX_GET_ELEMENT_ATTR_RSP, &avrc_rsp);
+    SEND_METAMSG_RSP(IDX_GET_ELEMENT_ATTR_RSP, &avrc_rsp, rc_index);
     return BT_STATUS_SUCCESS;
 }
 
@@ -1714,25 +3224,49 @@
 **
 ***************************************************************************/
 static bt_status_t register_notification_rsp(btrc_event_id_t event_id,
-    btrc_notification_type_t type, btrc_register_notification_t *p_param)
+    btrc_notification_type_t type, btrc_register_notification_t *p_param, bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
+    int index = btif_rc_get_idx_by_addr(bd_addr->address);
     CHECK_RC_CONNECTED
-    BTIF_TRACE_EVENT("## %s ## event_id:%s", __FUNCTION__, dump_rc_notification_event_id(event_id));
-    if (btif_rc_cb.rc_notif[event_id-1].bNotify == FALSE)
+
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+
+
+    BTIF_TRACE_IMP("## %s ## event_id:%s", __FUNCTION__, dump_rc_notification_event_id(event_id));
+    if (btif_rc_cb[index].rc_notif[event_id-1].bNotify == FALSE)
     {
         BTIF_TRACE_ERROR("Avrcp Event id not registered: event_id = %x", event_id);
         return BT_STATUS_NOT_READY;
     }
     memset(&(avrc_rsp.reg_notif), 0, sizeof(tAVRC_REG_NOTIF_RSP));
     avrc_rsp.reg_notif.event_id = event_id;
+    int av_index = btif_av_idx_by_bdaddr(bd_addr->address);
 
     switch(event_id)
     {
         case BTRC_EVT_PLAY_STATUS_CHANGED:
             avrc_rsp.reg_notif.param.play_status = p_param->play_status;
-            if (avrc_rsp.reg_notif.param.play_status == PLAY_STATUS_PLAYING)
+            /* Clear remote suspend flag, as remote device issues
+             * suspend within 3s after pause, and DUT within 3s
+             * initiates Play
+            */
+            BTIF_TRACE_ERROR("%s: play_status: %d",__FUNCTION__,
+                                  avrc_rsp.reg_notif.param.play_status);
+            if ((avrc_rsp.reg_notif.param.play_status == PLAY_STATUS_PLAYING) &&
+                (btif_av_check_flag_remote_suspend(av_index)))
+            {
+                BTIF_TRACE_ERROR("%s: clear remote suspend flag: %d",__FUNCTION__,av_index );
                 btif_av_clear_remote_suspend_flag();
+                if (btif_av_is_offload_supported())
+                {
+                    btif_dispatch_sm_event(BTIF_AV_START_STREAM_REQ_EVT, NULL, 0);
+                }
+            }
             break;
         case BTRC_EVT_TRACK_CHANGE:
             memcpy(&(avrc_rsp.reg_notif.param.track), &(p_param->track), sizeof(btrc_uid_t));
@@ -1740,6 +3274,29 @@
         case BTRC_EVT_PLAY_POS_CHANGED:
             avrc_rsp.reg_notif.param.play_pos = p_param->song_pos;
             break;
+        case BTRC_EVT_APP_SETTINGS_CHANGED:
+            if (interop_match_addr(INTEROP_DISABLE_PLAYER_APPLICATION_SETTING_CMDS,
+                    (bt_bdaddr_t *) bd_addr))
+            {
+                BTIF_TRACE_DEBUG("Blacklisted CK for BTRC_EVT_APP_SETTINGS_CHANGED event");
+                return BT_STATUS_UNHANDLED;
+            }
+            avrc_rsp.reg_notif.param.player_setting.num_attr = p_param->player_setting.num_attr;
+            memcpy(&avrc_rsp.reg_notif.param.player_setting.attr_id,
+                                       p_param->player_setting.attr_ids, 2);
+            memcpy(&avrc_rsp.reg_notif.param.player_setting.attr_value,
+                                       p_param->player_setting.attr_values, 2);
+            break;
+        case BTRC_EVT_ADDRESSED_PLAYER_CHANGED:
+            avrc_rsp.reg_notif.param.addr_player.player_id = p_param->player_id;
+            avrc_rsp.reg_notif.param.addr_player.uid_counter = 0;
+            break;
+        case BTRC_EVT_AVAILABLE_PLAYERS_CHANGED:
+            avrc_rsp.reg_notif.param.evt  = 0x0a;
+            break;
+        case BTRC_EVT_NOW_PLAYING_CONTENT_CHANGED:
+            avrc_rsp.reg_notif.param.evt  = 0x09;
+            break;
         default:
             BTIF_TRACE_WARNING("%s : Unhandled event ID : 0x%x", __FUNCTION__, event_id);
             return BT_STATUS_UNHANDLED;
@@ -1747,14 +3304,479 @@
 
     avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
     avrc_rsp.reg_notif.opcode = opcode_from_pdu(AVRC_PDU_REGISTER_NOTIFICATION);
-    avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
+    if (type == BTRC_NOTIFICATION_TYPE_REJECT)
+    {
+        /* Spec AVRCP 1.5 ,section 6.9.2.2, on completion
+         * of the addressed player changed notificatons the TG shall
+         * complete all player specific notification with AV/C C-type
+         * Rejected with error code Addressed Player changed.
+         * This will happen in case when music player has changed
+         * Application should take care of sending reject response.
+        */
+        avrc_rsp.get_play_status.status = AVRC_STS_ADDR_PLAYER_CHG;
+    }
+    else
+    {
+        avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
+    }
 
     /* Send the response. */
-    send_metamsg_rsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
+    send_metamsg_rsp(btif_rc_cb[index].rc_handle, btif_rc_cb[index].rc_notif[event_id-1].label,
         ((type == BTRC_NOTIFICATION_TYPE_INTERIM)?AVRC_CMD_NOTIF:AVRC_RSP_CHANGED), &avrc_rsp);
     return BT_STATUS_SUCCESS;
 }
 
+
+/***************************************************************************
+**
+** Function         get_folderitem_rsp
+**
+** Description      Response to Get Folder Items , PDU 0x71
+**
+** Returns          bt_status_t
+**
+***************************************************************************/
+static bt_status_t get_folderitem_rsp(btrc_folder_list_entries_t *rsp, bt_bdaddr_t *bd_addr)
+{
+    tAVRC_RESPONSE avrc_rsp;
+    tAVRC_ITEM item[MAX_FOLDER_RSP_SUPPORT]; //Number of players that could be supported
+    UINT8  index, i, xx, media_attr_cnt;
+    UINT8 *p_conversion;
+    int rc_index;
+    CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_EVENT("%s() AVRC_PDU_GET_FOLDER_ITEMS", __FUNCTION__);
+    index                             = IDX_GET_FOLDER_ITEMS_RSP ;
+    avrc_rsp.get_items.pdu            = AVRC_PDU_GET_FOLDER_ITEMS;
+    avrc_rsp.get_items.opcode         = AVRC_OP_BROWSE;
+    avrc_rsp.get_items.uid_counter    = rsp->uid_counter;
+    avrc_rsp.get_items.status         = rsp->status ;//4 means SUCCESS
+    avrc_rsp.get_items.item_count     = 0;
+    BTIF_TRACE_EVENT("status =%d, item_count =%d",rsp->status, rsp->item_count);
+
+    for (i=0; (i < rsp->item_count && i < MAX_FOLDER_RSP_SUPPORT) ; ++i)
+    {
+        item[i].item_type = rsp->p_item_list[i].item_type;
+        BTIF_TRACE_EVENT("item_type  = %d", rsp->p_item_list[i].item_type);
+        switch (item[i].item_type)
+        {
+            case AVRC_ITEM_PLAYER:
+                memcpy(item[i].u.player.features, rsp->p_item_list[i].u.player.features,
+                            AVRC_FEATURE_MASK_SIZE);
+                item[i].u.player.major_type      =  rsp->p_item_list[i].u.player.major_type;
+                item[i].u.player.sub_type        =  rsp->p_item_list[i].u.player.sub_type;
+                item[i].u.player.play_status     =  rsp->p_item_list[i].u.player.play_status;
+                item[i].u.player.player_id       =  rsp->p_item_list[i].u.player.player_id;
+                item[i].u.player.name.charset_id =  rsp->p_item_list[i].u.player.name.charset_id;
+                item[i].u.player.name.str_len    =  rsp->p_item_list[i].u.player.name.str_len;
+                item[i].u.player.name.p_str      =  rsp->p_item_list[i].u.player.name.p_str;
+                ++avrc_rsp.get_items.item_count;
+            break;
+
+            case AVRC_ITEM_FOLDER:
+                item[i].u.folder.type            =  rsp->p_item_list[i].u.folder.type;
+                item[i].u.folder.playable        =  rsp->p_item_list[i].u.folder.playable;
+                {
+                    p_conversion = (UINT8*)&(rsp->p_item_list[i].u.folder.uid);
+                    for (xx = 0; xx < AVRC_UID_SIZE; xx++)
+                    {
+                        ((UINT8 *) item[i].u.folder.uid)[AVRC_UID_SIZE - (xx + 1)] = \
+                                                                        *p_conversion++;
+                    }
+                }
+
+                item[i].u.folder.name.charset_id =  rsp->p_item_list[i].u.folder.name.charset_id;
+                item[i].u.folder.name.str_len    =  rsp->p_item_list[i].u.folder.name.str_len;
+                item[i].u.folder.name.p_str      =  rsp->p_item_list[i].u.folder.name.p_str;
+                ++avrc_rsp.get_items.item_count;
+            break;
+
+            case AVRC_ITEM_MEDIA:
+                item[i].u.media.type             =  rsp->p_item_list[i].u.media.type;
+                {
+                    p_conversion = (UINT8*)&(rsp->p_item_list[i].u.media.uid);
+                    //BE_STREAM_TO_ARRAY(p_conversion, item[i].u.folder.uid, AVRC_UID_SIZE);
+                    for (xx = 0; xx < AVRC_UID_SIZE; xx++)
+                    {
+                        ((UINT8 *) item[i].u.folder.uid)[AVRC_UID_SIZE - (xx + 1)] = \
+                                                                        *p_conversion++;
+                    }
+                }
+                item[i].u.media.name.charset_id  =  rsp->p_item_list[i].u.media.name.charset_id;
+                item[i].u.media.name.str_len     =  rsp->p_item_list[i].u.media.name.str_len;
+                item[i].u.media.name.p_str       =  rsp->p_item_list[i].u.media.name.p_str;
+                media_attr_cnt                   =  rsp->p_item_list[i].u.media.attr_count;
+                item[i].u.media.attr_count       =  rsp->p_item_list[i].u.media.attr_count;
+                BTIF_TRACE_ERROR("attr count = %d", media_attr_cnt);
+                if (media_attr_cnt > 0)
+                {
+                    if ((item[i].u.media.p_attr_list = \
+                    (tAVRC_ATTR_ENTRY *)osi_malloc((UINT16)(media_attr_cnt * \
+                                                        sizeof(tAVRC_ATTR_ENTRY)))) != NULL)
+                    {
+                        for (xx = 0; xx < media_attr_cnt; xx++)
+                        {
+                            item[i].u.media.p_attr_list[xx].attr_id = \
+                                rsp->p_item_list[i].u.media.p_attr_list[xx].attr_id;
+                            item[i].u.media.p_attr_list[xx].name.charset_id = \
+                                rsp->p_item_list[i].u.media.p_attr_list[xx].name.charset_id;
+                            item[i].u.media.p_attr_list[xx].name.str_len = \
+                                rsp->p_item_list[i].u.media.p_attr_list[xx].name.str_len;
+                            item[i].u.media.p_attr_list[xx].name.p_str = \
+                                rsp->p_item_list[i].u.media.p_attr_list[xx].name.p_str;
+                            BTIF_TRACE_ERROR("attr_id = %d", item[i].u.media.p_attr_list[xx].\
+                                attr_id);
+                            BTIF_TRACE_ERROR("str_len = %d", item[i].u.media.p_attr_list[xx].\
+                                name.str_len);
+                        }
+                    }
+                    else
+                    {
+                        BTIF_TRACE_ERROR("Not enough buffer allocated to accomodate attributes");
+                        item[i].u.media.attr_count =  0;
+                    }
+                }
+                ++avrc_rsp.get_items.item_count;
+            break;
+
+            default:
+                return BT_STATUS_UNHANDLED;
+            break;
+        }
+    }
+    if (avrc_rsp.get_items.item_count == 0) {
+        /*As per spec Send proper Error if no Music App is registered.*/
+        avrc_rsp.get_items.status = AVRC_STS_BAD_RANGE;
+    }
+    avrc_rsp.get_items.p_item_list = item;
+    app_sendbrowsemsg(IDX_GET_FOLDER_ITEMS_RSP ,&avrc_rsp, rc_index);
+    BTIF_TRACE_ERROR("free attr list");
+    for (i=0; (i < rsp->item_count && i < MAX_FOLDER_RSP_SUPPORT) ; ++i)
+    {
+        if (item[i].item_type == AVRC_ITEM_MEDIA)
+        {
+            if (rsp->p_item_list[i].u.media.attr_count > 0)
+            {
+                osi_free_and_reset((void**)&item[i].u.media.p_attr_list);
+            }
+        }
+    }
+    return BT_STATUS_SUCCESS;
+}
+
+/**********************************************************************
+**
+** Function        set_addrplayer_rsp
+**
+** Description     Response to Set Addressed Player , PDU 0x60
+**
+** Return          status
+**
+*********************************************************************/
+
+static bt_status_t set_addrplayer_rsp(btrc_status_t status_code, bt_bdaddr_t *bd_addr)
+{
+    tAVRC_RESPONSE avrc_rsp;
+    int rc_index;
+    CHECK_RC_CONNECTED
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
+    avrc_rsp.addr_player.status = status_code;
+    avrc_rsp.addr_player.opcode = opcode_from_pdu(AVRC_PDU_SET_ADDRESSED_PLAYER);
+    avrc_rsp.addr_player.pdu    = AVRC_PDU_SET_ADDRESSED_PLAYER;
+    /* Send the response */
+    SEND_METAMSG_RSP(IDX_SET_ADDRESS_PLAYER_RSP, &avrc_rsp, rc_index);
+    return BT_STATUS_SUCCESS;
+}
+
+/**********************************************************************
+**
+** Function        set_browseplayer_rsp
+**
+** Description     Response to Set Browsed Player , PDU 0x70
+**
+** Return          status
+**
+*********************************************************************/
+
+static bt_status_t set_browseplayer_rsp(btrc_set_browsed_player_rsp_t *p_param, bt_bdaddr_t *bd_addr)
+{
+    tAVRC_RESPONSE avrc_rsp;
+    int rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    CHECK_RC_CONNECTED
+
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
+
+    avrc_rsp.br_player.pdu = AVRC_PDU_SET_BROWSED_PLAYER;
+    avrc_rsp.br_player.folder_depth = p_param->folder_depth;
+    avrc_rsp.br_player.charset_id = p_param->charset_id;
+    avrc_rsp.br_player.num_items = p_param->num_items;
+    avrc_rsp.br_player.opcode = opcode_from_pdu(AVRC_PDU_SET_BROWSED_PLAYER);
+    avrc_rsp.br_player.status = p_param->status;
+    avrc_rsp.br_player.uid_counter = p_param->uid_counter;
+    avrc_rsp.br_player.p_folders = (tAVRC_NAME*)p_param->p_folders;
+    /* Send the response */
+    SEND_BROWSEMSG_RSP(IDX_SET_BROWSE_PLAYER_RSP, &avrc_rsp, rc_index);
+    return BT_STATUS_SUCCESS;
+}
+
+/**********************************************************************
+**
+** Function        changepath_rsp
+**
+** Description     Response to Change Path , PDU 0x60
+**
+** Return          status
+**
+*********************************************************************/
+
+static bt_status_t changepath_rsp(uint8_t status_code, uint32_t item_count, bt_bdaddr_t *bd_addr)
+{
+    tAVRC_RESPONSE avrc_rsp;
+    int rc_index;
+    CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
+
+    avrc_rsp.chg_path.num_items = item_count;
+    avrc_rsp.chg_path.opcode = opcode_from_pdu(AVRC_PDU_CHANGE_PATH);
+    avrc_rsp.chg_path.pdu = AVRC_PDU_CHANGE_PATH;
+    avrc_rsp.chg_path.status = status_code;
+    /* Send the response */
+    SEND_BROWSEMSG_RSP(IDX_CHANGE_PATH_RSP, &avrc_rsp, rc_index);
+    return BT_STATUS_SUCCESS;
+}
+
+/**********************************************************************
+ **
+ ** Function        get_totalitems_rsp
+ **
+ ** Description     Response to Get Total number of Items , PDU 0x75
+ **
+ ** Return          status
+ **
+ *********************************************************************/
+
+ static bt_status_t get_total_items_rsp(uint8_t status_code, uint32_t item_count,
+         uint16_t uid_counter, bt_bdaddr_t *bd_addr)
+ {
+     tAVRC_RESPONSE avrc_rsp;
+     int rc_index;
+     CHECK_RC_CONNECTED
+
+     rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+
+     if (rc_index == btif_max_rc_clients)
+     {
+         BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+         return BT_STATUS_FAIL;
+     }
+     BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
+     avrc_rsp.get_tot_items.num_items = item_count;
+     avrc_rsp.get_tot_items.opcode = opcode_from_pdu(AVRC_PDU_GET_TOTAL_NUMBER_OF_ITEMS);
+     avrc_rsp.get_tot_items.pdu = AVRC_PDU_GET_TOTAL_NUMBER_OF_ITEMS;
+     avrc_rsp.get_tot_items.status = status_code;
+     avrc_rsp.get_tot_items.uid_counter = uid_counter;
+     /* Send the response */
+     SEND_BROWSEMSG_RSP(IDX_GET_TOTAL_ITEMS_RSP, &avrc_rsp, rc_index);
+     return BT_STATUS_SUCCESS;
+ }
+
+/**********************************************************************
+**
+** Function        playitem_rsp
+**
+** Description     Response to Play Item , PDU 0x60
+**
+** Return          status
+**
+*********************************************************************/
+
+static bt_status_t playitem_rsp(uint8_t status_code, bt_bdaddr_t *bd_addr)
+{
+    tAVRC_RESPONSE avrc_rsp;
+    int rc_index;
+    CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
+
+    avrc_rsp.play_item.status = status_code;
+    avrc_rsp.play_item.opcode = opcode_from_pdu(AVRC_PDU_PLAY_ITEM);
+    avrc_rsp.play_item.pdu    = AVRC_PDU_PLAY_ITEM;
+    /* Send the response */
+    SEND_METAMSG_RSP(IDX_PLAY_ITEM_RSP, &avrc_rsp,rc_index);
+
+    return BT_STATUS_SUCCESS;
+}
+
+/**********************************************************************
+**
+** Function        get_itemattr_rsp
+**
+** Description     Response to Get Item , PDU 0x60
+**
+** Return          status
+**
+*********************************************************************/
+
+static bt_status_t get_itemattr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p_attrs, bt_bdaddr_t *bd_addr)
+
+{
+    tAVRC_RESPONSE avrc_rsp;
+    UINT32 i;
+    tAVRC_ATTR_ENTRY element_attrs[MAX_ELEM_ATTR_SIZE];
+    int rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    CHECK_RC_CONNECTED
+
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
+
+    if (num_attr == 0 || num_attr > MAX_ELEM_ATTR_SIZE)
+    {
+        avrc_rsp.get_attrs.status = AVRC_STS_INTERNAL_ERR;
+    }
+    else
+    {
+        memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
+        for (i=0; i<num_attr; i++)
+        {
+            element_attrs[i].attr_id = p_attrs[i].attr_id;
+            element_attrs[i].name.charset_id = AVRC_CHARSET_ID_UTF8;
+            element_attrs[i].name.str_len = (UINT16)strlen((char *)p_attrs[i].text);
+            element_attrs[i].name.p_str = p_attrs[i].text;
+            BTIF_TRACE_DEBUG("%s attr_id:0x%x, charset_id:0x%x, str_len:%d, str:%s",
+                __FUNCTION__, (unsigned int)element_attrs[i].attr_id,
+                element_attrs[i].name.charset_id,
+                element_attrs[i].name.str_len,
+                element_attrs[i].name.p_str);
+        }
+        avrc_rsp.get_attrs.status = AVRC_STS_NO_ERROR;
+    }
+    avrc_rsp.get_attrs.attr_count = num_attr;
+    avrc_rsp.get_attrs.p_attr_list = element_attrs;
+    avrc_rsp.get_attrs.pdu = AVRC_PDU_GET_ITEM_ATTRIBUTES;
+    avrc_rsp.get_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ITEM_ATTRIBUTES);
+    /* Send the response */
+    SEND_BROWSEMSG_RSP(IDX_GET_ITEM_ATTR_RSP, &avrc_rsp, rc_index);
+    return BT_STATUS_SUCCESS;
+}
+
+/**********************************************************************
+**
+** Function        is_device_active_in_handoff
+**
+** Description     Check if this is the active device during hand-off
+**                 If the multicast is disabled when connected to more
+**                 than one device and the active playing device is
+**                 different or device to start playback is different
+**                 then fail this condition.
+** Return          BT_STATUS_SUCCESS if active BT_STATUS_FAIL otherwise
+**
+*********************************************************************/
+static bt_status_t is_device_active_in_handoff(bt_bdaddr_t *bd_addr)
+{
+    BD_ADDR playing_device;
+    int rc_index;
+    UINT16 connected_devices, playing_devices;
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if(rc_index >= btif_max_rc_clients)
+    {
+        return BT_STATUS_FAIL;
+    }
+    connected_devices = btif_av_get_num_connected_devices();
+    playing_devices = btif_av_get_num_playing_devices();
+
+    if((connected_devices < btif_max_rc_clients) || (playing_devices > 1))
+    {
+        return BT_STATUS_SUCCESS;
+    }
+
+    if((connected_devices > 1) && (playing_devices == 1))
+    {
+        /* One playing device, check the active device */
+        btif_get_latest_playing_device(playing_device);
+        if (bdcmp(bd_addr->address, playing_device) == 0)
+        {
+            return BT_STATUS_SUCCESS;
+        }
+        else
+        {
+            return BT_STATUS_FAIL;
+        }
+    }
+    else if (playing_devices == 0)
+    {
+        /* No Playing device, find the next playing device
+         * Play initiated from remote
+         */
+        if (btif_rc_cb[rc_index].rc_play_processed == TRUE)
+        {
+            return BT_STATUS_SUCCESS;
+        }
+        else if (btif_av_is_current_device(bd_addr->address) == TRUE)
+        {
+            /* Play initiated locally. check the current device and
+             * make sure play is not initiated from other remote
+             */
+            BD_ADDR rc_play_device = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+            btif_rc_get_playing_device(rc_play_device);
+            if(bdcmp(bd_addr->address, bd_addr_null) != 0)
+            {
+                /* some other playing device */
+                return BT_STATUS_FAIL;
+            }
+            return BT_STATUS_SUCCESS;
+        }
+        else
+        {
+            BTIF_TRACE_ERROR("%s no playing or current device ", __FUNCTION__);
+            return BT_STATUS_FAIL;
+        }
+    }
+    else
+    {
+        BTIF_TRACE_ERROR("%s unchecked state: connected devices: %d playing devices: %d",
+            __FUNCTION__, connected_devices, playing_devices);
+        return BT_STATUS_SUCCESS;
+    }
+}
+
 /***************************************************************************
 **
 ** Function         set_volume
@@ -1769,22 +3791,29 @@
 ** Returns          bt_status_t
 **
 ***************************************************************************/
-static bt_status_t set_volume(uint8_t volume)
+static bt_status_t set_volume(uint8_t volume, bt_bdaddr_t *bd_addr)
 {
-    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
+    int index = btif_rc_get_idx_by_addr(bd_addr->address);
+
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, index);
     CHECK_RC_CONNECTED
     tAVRC_STS status = BT_STATUS_UNSUPPORTED;
     rc_transaction_t *p_transaction=NULL;
 
-    if (btif_rc_cb.rc_volume==volume)
+    if(btif_rc_cb[index].rc_volume==volume)
     {
         status=BT_STATUS_DONE;
         BTIF_TRACE_ERROR("%s: volume value already set earlier: 0x%02x",__FUNCTION__, volume);
         return status;
     }
 
-    if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG) &&
-        (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL))
+    if ((btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG) &&
+        (btif_rc_cb[index].rc_features & BTA_AV_FEAT_ADV_CTRL))
     {
         tAVRC_COMMAND avrc_cmd = {0};
         BT_HDR *p_msg = NULL;
@@ -1802,7 +3831,7 @@
             {
                 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
                                    __FUNCTION__,p_transaction->lbl);
-                BTA_AvMetaCmd(btif_rc_cb.rc_handle,p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
+                BTA_AvMetaCmd(btif_rc_cb[index].rc_handle,p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
                 status =  BT_STATUS_SUCCESS;
             }
             else
@@ -1836,13 +3865,12 @@
 **
 ***************************************************************************/
 
-static void register_volumechange (UINT8 lbl)
+static void register_volumechange (UINT8 lbl, int index)
 {
     tAVRC_COMMAND avrc_cmd = {0};
     BT_HDR *p_msg = NULL;
     tAVRC_STS BldResp=AVRC_STS_BAD_CMD;
     rc_transaction_t *p_transaction=NULL;
-
     BTIF_TRACE_DEBUG("%s called with label:%d",__FUNCTION__,lbl);
 
     avrc_cmd.cmd.opcode=0x00;
@@ -1855,7 +3883,7 @@
     if (AVRC_STS_NO_ERROR == BldResp && p_msg) {
         p_transaction = get_transaction_by_lbl(lbl);
         if (p_transaction != NULL) {
-            BTA_AvMetaCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
+            BTA_AvMetaCmd(btif_rc_cb[index].rc_handle, p_transaction->lbl,
                           AVRC_CMD_NOTIF, p_msg);
             BTIF_TRACE_DEBUG("%s:BTA_AvMetaCmd called", __func__);
          } else {
@@ -1879,11 +3907,19 @@
 ***************************************************************************/
 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
 {
+    UINT8 index;  /*For RC it is zero*/
     tAVRC_RESPONSE    avrc_response = {0};
     UINT8             scratch_buf[512] = {0};
     tAVRC_STS status = BT_STATUS_UNSUPPORTED;
 
-    if (AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode &&(AVRC_RSP_CHANGED==pmeta_msg->code
+    index = btif_rc_get_idx_by_rc_handle(pmeta_msg->rc_handle);
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return;
+    }
+
+    if(AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode &&(AVRC_RSP_CHANGED==pmeta_msg->code
       || AVRC_RSP_INTERIM==pmeta_msg->code || AVRC_RSP_ACCEPT==pmeta_msg->code
       || AVRC_RSP_REJ==pmeta_msg->code || AVRC_RSP_NOT_IMPL==pmeta_msg->code))
     {
@@ -1896,10 +3932,10 @@
         {
             if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
                 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
-                && btif_rc_cb.rc_vol_label==pmeta_msg->label)
+                && btif_rc_cb[index].rc_vol_label==pmeta_msg->label)
             {
-                btif_rc_cb.rc_vol_label=MAX_LABEL;
-                release_transaction(btif_rc_cb.rc_vol_label);
+                btif_rc_cb[index].rc_vol_label=MAX_LABEL;
+                release_transaction(btif_rc_cb[index].rc_vol_label);
             }
             else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
             {
@@ -1909,7 +3945,7 @@
         }
         else if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
             && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
-            && btif_rc_cb.rc_vol_label!=pmeta_msg->label)
+            && btif_rc_cb[index].rc_vol_label!=pmeta_msg->label)
             {
                 // Just discard the message, if the device sends back with an incorrect label
                 BTIF_TRACE_DEBUG("%s:Discarding register notfn in rsp.code: %d and label %d",
@@ -1930,7 +3966,7 @@
      {
          /* re-register for volume change notification */
          // Do not re-register for rejected case, as it might get into endless loop
-         register_volumechange(btif_rc_cb.rc_vol_label);
+         register_volumechange(btif_rc_cb[index].rc_vol_label, index);
      }
      else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
      {
@@ -1941,7 +3977,7 @@
      BTIF_TRACE_EVENT("%s: Passing received metamsg response to app. pdu: %s",
              __FUNCTION__, dump_rc_pdu(avrc_response.pdu));
      btif_rc_upstreams_rsp_evt((uint16_t)avrc_response.rsp.pdu, &avrc_response, pmeta_msg->code,
-                                pmeta_msg->label);
+                                pmeta_msg->label, index);
 }
 #endif
 
@@ -1991,7 +4027,7 @@
 
     if (p_event->label == label)
     {
-        list_remove(btif_rc_cb.rc_supported_event_list, p_event);
+        list_remove(btif_rc_cb[0].rc_supported_event_list, p_event);
         return false;
     }
     return true;
@@ -2010,13 +4046,14 @@
 static void rc_notification_interim_timout (UINT8 label)
 {
     list_node_t *node;
-
-    list_foreach(btif_rc_cb.rc_supported_event_list,
+    if (btif_rc_cb[0].rc_supported_event_list == NULL)
+        return;
+    list_foreach(btif_rc_cb[0].rc_supported_event_list,
                      iterate_supported_event_list_for_timeout, &label);
     /* Timeout happened for interim response for the registered event,
      * check if there are any pending for registration
      */
-    node = list_begin(btif_rc_cb.rc_supported_event_list);
+    node = list_begin(btif_rc_cb[0].rc_supported_event_list);
     while (node != NULL)
     {
         btif_rc_supported_event_t *p_event;
@@ -2051,7 +4088,7 @@
 
     p_context = (btif_rc_timer_context_t *)data;
     memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
-    meta_msg.rc_handle = btif_rc_cb.rc_handle;
+    meta_msg.rc_handle = btif_rc_cb[0].rc_handle;
 
     switch (p_context->rc_status_cmd.pdu_id) {
     case AVRC_PDU_REGISTER_NOTIFICATION:
@@ -2136,7 +4173,7 @@
     tBTA_AV_META_MSG    meta_msg;
 
     memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
-    meta_msg.rc_handle = btif_rc_cb.rc_handle;
+    meta_msg.rc_handle = btif_rc_cb[0].rc_handle;
 
     switch (p_context->rc_control_cmd.pdu_id) {
     case AVRC_PDU_SET_PLAYER_APP_VALUE:
@@ -2208,12 +4245,12 @@
 static void rc_start_play_status_timer(void)
 {
     /* Start the Play status timer only if it is not started */
-    if (!alarm_is_scheduled(btif_rc_cb.rc_play_status_timer)) {
-        if (btif_rc_cb.rc_play_status_timer == NULL) {
-            btif_rc_cb.rc_play_status_timer =
+    if (!alarm_is_scheduled(btif_rc_cb[0].rc_play_status_timer)) {
+        if (btif_rc_cb[0].rc_play_status_timer == NULL) {
+            btif_rc_cb[0].rc_play_status_timer =
                 alarm_new("btif_rc.rc_play_status_timer");
         }
-        alarm_set_on_queue(btif_rc_cb.rc_play_status_timer,
+        alarm_set_on_queue(btif_rc_cb[0].rc_play_status_timer,
                            BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
                            btif_rc_play_status_timer_timeout, NULL,
                            btu_general_alarm_queue);
@@ -2230,8 +4267,8 @@
 ***************************************************************************/
 void rc_stop_play_status_timer()
 {
-    if (btif_rc_cb.rc_play_status_timer != NULL)
-        alarm_cancel(btif_rc_cb.rc_play_status_timer);
+    if (btif_rc_cb[0].rc_play_status_timer != NULL)
+        alarm_cancel(btif_rc_cb[0].rc_play_status_timer);
 }
 
 /***************************************************************************
@@ -2336,7 +4373,7 @@
         btif_rc_supported_event_t *p_event;
 
         /* Todo: Check if list can be active when we hit here */
-        btif_rc_cb.rc_supported_event_list = list_new(osi_free);
+        btif_rc_cb[0].rc_supported_event_list = list_new(osi_free);
         for (xx = 0; xx < p_rsp->count; xx++)
         {
             /* Skip registering for Play position change notification */
@@ -2347,10 +4384,15 @@
                 p_event = (btif_rc_supported_event_t *)osi_malloc(sizeof(btif_rc_supported_event_t));
                 p_event->event_id = p_rsp->param.event_id[xx];
                 p_event->status = eNOT_REGISTERED;
-                list_append(btif_rc_cb.rc_supported_event_list, p_event);
+                list_append(btif_rc_cb[0].rc_supported_event_list, p_event);
             }
         }
-        p_event = list_front(btif_rc_cb.rc_supported_event_list);
+        if (list_is_empty(btif_rc_cb[0].rc_supported_event_list))
+        {
+            BTIF_TRACE_EVENT(" Supported event list Empty, returning");
+            return;
+        }
+        p_event = list_front(btif_rc_cb[0].rc_supported_event_list);
         if (p_event != NULL)
         {
             register_for_event_notification(p_event);
@@ -2414,11 +4456,13 @@
         };
 
 
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 
     if (pmeta_msg->code == AVRC_RSP_INTERIM)
     {
-        btif_rc_supported_event_t *p_event;
+        /* Klockwork Fix for below issue 4442
+         * 'p_event' might be used uninitialized in this function.*/
+        btif_rc_supported_event_t *p_event = NULL;
         list_node_t *node;
 
         BTIF_TRACE_DEBUG("%s Interim response : 0x%2X ", __FUNCTION__, p_rsp->event_id);
@@ -2447,7 +4491,7 @@
                     /* Update the UID for current track
                      * Attributes will be fetched after the AVRCP procedure
                      */
-                    BE_STREAM_TO_UINT64(btif_rc_cb.rc_playing_uid, p_data);
+                    BE_STREAM_TO_UINT64(btif_rc_cb[0].rc_playing_uid, p_data);
                 }
                 break;
 
@@ -2476,11 +4520,11 @@
                     p_rsp->event_id);
                 return;
         }
-        list_foreach(btif_rc_cb.rc_supported_event_list,
+        list_foreach(btif_rc_cb[0].rc_supported_event_list,
                 iterate_supported_event_list_for_interim_rsp,
                 &p_rsp->event_id);
 
-        node = list_begin(btif_rc_cb.rc_supported_event_list);
+        node = list_begin(btif_rc_cb[0].rc_supported_event_list);
         while (node != NULL)
         {
             p_event = (btif_rc_supported_event_t *)list_node(node);
@@ -2493,13 +4537,13 @@
             p_event = NULL;
         }
         /* Registered for all events, we can request application settings */
-        if ((p_event == NULL) && (btif_rc_cb.rc_app_settings.query_started == false))
+        if ((p_event == NULL) && (btif_rc_cb[0].rc_app_settings.query_started == false))
         {
             /* we need to do this only if remote TG supports
              * player application settings
              */
-            btif_rc_cb.rc_app_settings.query_started = TRUE;
-            if (btif_rc_cb.rc_features & BTA_AV_FEAT_APP_SETTING)
+            btif_rc_cb[0].rc_app_settings.query_started = TRUE;
+            if (btif_rc_cb[0].rc_features & BTA_AV_FEAT_APP_SETTING)
             {
                 list_player_app_setting_attrib_cmd();
             }
@@ -2518,7 +4562,7 @@
         BTIF_TRACE_DEBUG("%s Notification completed : 0x%2X ", __FUNCTION__,
             p_rsp->event_id);
 
-        node = list_begin(btif_rc_cb.rc_supported_event_list);
+        node = list_begin(btif_rc_cb[0].rc_supported_event_list);
         while (node != NULL)
         {
             p_event = (btif_rc_supported_event_t *)list_node(node);
@@ -2554,7 +4598,11 @@
                 {
                     break;
                 }
-                get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
+                UINT8 *p_data = p_rsp->param.track;
+                BE_STREAM_TO_UINT64(btif_rc_cb[0].rc_playing_uid, p_data);
+                /* Fix for below Klowkwork Issue at line 4509
+                 * Array 'attr_list' of size 7 may use index value(s) 7 */
+                get_element_attribute_cmd (sizeof(attr_list)/sizeof(UINT32), attr_list);
                 break;
 
             case AVRC_EVT_APP_SETTING_CHANGE:
@@ -2625,26 +4673,28 @@
 
         if (p_rsp->attrs[xx] > AVRC_PLAYER_SETTING_LOW_MENU_EXT)
         {
-            st_index = btif_rc_cb.rc_app_settings.num_ext_attrs;
-            btif_rc_cb.rc_app_settings.ext_attrs[st_index].attr_id = p_rsp->attrs[xx];
-            btif_rc_cb.rc_app_settings.num_ext_attrs++;
+            st_index = btif_rc_cb[0].rc_app_settings.num_ext_attrs;
+            btif_rc_cb[0].rc_app_settings.ext_attrs[st_index].attr_id = p_rsp->attrs[xx];
+            btif_rc_cb[0].rc_app_settings.num_ext_attrs++;
         }
         else
         {
-            st_index = btif_rc_cb.rc_app_settings.num_attrs;
-            btif_rc_cb.rc_app_settings.attrs[st_index].attr_id = p_rsp->attrs[xx];
-            btif_rc_cb.rc_app_settings.num_attrs++;
+            st_index = btif_rc_cb[0].rc_app_settings.num_attrs;
+            btif_rc_cb[0].rc_app_settings.attrs[st_index].attr_id = p_rsp->attrs[xx];
+            btif_rc_cb[0].rc_app_settings.num_attrs++;
         }
     }
-    btif_rc_cb.rc_app_settings.attr_index = 0;
-    btif_rc_cb.rc_app_settings.ext_attr_index = 0;
-    btif_rc_cb.rc_app_settings.ext_val_index = 0;
+    btif_rc_cb[0].rc_app_settings.attr_index = 0;
+    btif_rc_cb[0].rc_app_settings.ext_attr_index = 0;
+    btif_rc_cb[0].rc_app_settings.ext_val_index = 0;
     if (p_rsp->num_attr)
     {
-        list_player_app_setting_value_cmd (btif_rc_cb.rc_app_settings.attrs[0].attr_id);
+        list_player_app_setting_value_cmd (btif_rc_cb[0].rc_app_settings.attrs[0].attr_id);
     }
     else
     {
+        /* Complete RC procedure from here */
+        rc_ctrl_procedure_complete();
         BTIF_TRACE_ERROR("%s No Player application settings found",
                 __FUNCTION__);
     }
@@ -2677,8 +4727,8 @@
         return;
     }
 
-    p_app_settings = &btif_rc_cb.rc_app_settings;
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+    p_app_settings = &btif_rc_cb[0].rc_app_settings;
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 
     if (p_app_settings->attr_index < p_app_settings->num_attrs)
     {
@@ -2700,8 +4750,12 @@
             p_app_settings->ext_attr_index = 0;
             list_player_app_setting_value_cmd (p_app_settings->ext_attrs[attr_index].attr_id);
         }
+        /* Klockwork fix for below line 4661
+         * Array 'attrs' of size 16 may use index value(s) 16..254*/
         else
         {
+            if (p_app_settings->num_attrs > AVRC_MAX_APP_ATTR_SIZE)
+                p_app_settings->num_attrs = AVRC_MAX_APP_ATTR_SIZE;
             for (xx = 0; xx < p_app_settings->num_attrs; xx++)
             {
                 attrs[xx] = p_app_settings->attrs[xx].attr_id;
@@ -2721,21 +4775,7 @@
         }
         attr_index++;
         p_app_settings->ext_attr_index++;
-        if (attr_index < p_app_settings->num_ext_attrs)
-        {
-            list_player_app_setting_value_cmd (p_app_settings->ext_attrs[p_app_settings->ext_attr_index].attr_id);
-        }
-        else
-        {
-            UINT8 attr[AVRC_MAX_APP_ATTR_SIZE];
-            UINT8 xx;
-
-            for (xx = 0; xx < p_app_settings->num_ext_attrs; xx++)
-            {
-                attr[xx] = p_app_settings->ext_attrs[xx].attr_id;
-            }
-            get_player_app_setting_attr_text_cmd(attr, xx);
-        }
+        list_player_app_setting_value_cmd (p_app_settings->ext_attrs[p_app_settings->ext_attr_index].attr_id);
     }
 }
 
@@ -2762,7 +4802,7 @@
         return;
     }
 
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 
     app_settings.num_attr = p_rsp->num_val;
 
@@ -2803,8 +4843,8 @@
     btif_rc_player_app_settings_t *p_app_settings;
     bt_bdaddr_t rc_addr;
 
-    p_app_settings = &btif_rc_cb.rc_app_settings;
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+    p_app_settings = &btif_rc_cb[0].rc_app_settings;
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 
     /* Todo: Do we need to retry on command timeout */
     if (p_rsp->status != AVRC_STS_NO_ERROR)
@@ -2821,8 +4861,9 @@
         for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
             osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
         p_app_settings->ext_attr_index = 0;
-
-        for (xx = 0; xx < p_app_settings->num_attrs; xx++)
+        /* Klockwork Fix for below issue at line 4765
+         * Array 'attrs' of size 16 may use index value(s) 16..254 */
+        for (xx = 0; xx < p_app_settings->num_attrs && xx < AVRC_MAX_APP_ATTR_SIZE; xx++)
         {
             attrs[xx] = p_app_settings->attrs[xx].attr_id;
         }
@@ -2848,7 +4889,9 @@
         }
     }
 
-    for (xx = 0; xx < p_app_settings->ext_attrs[0].num_val; xx++)
+    /* Klockwork Fix for below issue at line 4791
+     * Array 'vals' of size 16 may use index value(s) 16..254*/
+    for (xx = 0; xx < p_app_settings->ext_attrs[0].num_val && xx < AVRC_MAX_APP_ATTR_SIZE; xx++)
     {
         vals[xx] = p_app_settings->ext_attrs[0].ext_attr_val[xx].val;
     }
@@ -2874,8 +4917,8 @@
     btif_rc_player_app_settings_t *p_app_settings;
     bt_bdaddr_t rc_addr;
 
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
-    p_app_settings = &btif_rc_cb.rc_app_settings;
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
+    p_app_settings = &btif_rc_cb[0].rc_app_settings;
 
     /* Todo: Do we need to retry on command timeout */
     if (p_rsp->status != AVRC_STS_NO_ERROR)
@@ -2902,7 +4945,9 @@
         }
         p_app_settings->ext_attr_index = 0;
 
-        for (xx = 0; xx < p_app_settings->num_attrs; xx++)
+        /* Klockwork Fix for below issue 4851
+         * Array 'attrss' of size 16 may use index value(s) 16..254*/
+        for (xx = 0; xx < p_app_settings->num_attrs && xx < AVRC_MAX_APP_ATTR_SIZE; xx++)
         {
             attrs[xx] = p_app_settings->attrs[xx].attr_id;
         }
@@ -2934,7 +4979,9 @@
     if (p_app_settings->ext_val_index < p_app_settings->num_ext_attrs)
     {
         attr_index = p_app_settings->ext_val_index;
-        for (xx = 0; xx < p_app_settings->ext_attrs[attr_index].num_val; xx++)
+        /* Klockwork Fix for below issue 4883
+         * Array 'vals' of size 16 may use index value(s) 16..254*/
+        for (xx = 0; xx < p_app_settings->ext_attrs[attr_index].num_val && xx < AVRC_MAX_APP_ATTR_SIZE; xx++)
         {
             vals[xx] = p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val;
         }
@@ -2944,18 +4991,25 @@
     {
         UINT8 x;
 
-        for (xx = 0; xx < p_app_settings->num_attrs; xx++)
+        for (xx = 0; ((xx < AVRC_MAX_APP_ATTR_SIZE) && (xx < p_app_settings->num_attrs)); xx++)
         {
             attrs[xx] = p_app_settings->attrs[xx].attr_id;
         }
-        for (x = 0; x < p_app_settings->num_ext_attrs; x++)
+        for (x = 0; ((xx + x < AVRC_MAX_APP_ATTR_SIZE) && (x < p_app_settings->num_ext_attrs)); x++)
         {
             attrs[xx+x] = p_app_settings->ext_attrs[x].attr_id;
         }
         HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
                     p_app_settings->num_attrs, p_app_settings->attrs,
                     p_app_settings->num_ext_attrs, p_app_settings->ext_attrs);
-        get_player_app_setting_cmd (xx + x, attrs);
+        if(xx+x > AVRC_MAX_APP_ATTR_SIZE)
+        {
+            get_player_app_setting_cmd (AVRC_MAX_APP_ATTR_SIZE, attrs);
+        }
+        else
+        {
+           get_player_app_setting_cmd (xx + x, attrs);
+        }
 
         /* Free the application settings information after sending to
          * application.
@@ -2988,7 +5042,7 @@
     uint8_t accepted = 0;
     bt_bdaddr_t rc_addr;
 
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 
     /* For timeout pmeta_msg will be NULL, else we need to
      * check if this is accepted by TG
@@ -3018,7 +5072,7 @@
         btrc_element_attr_val_t *p_attr =
             (btrc_element_attr_val_t *)osi_calloc(buf_size);
 
-        bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+        bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 
         for (int i = 0; i < p_rsp->num_attr; i++) {
             p_attr[i].attr_id = p_rsp->p_attrs[i].attr_id;
@@ -3046,7 +5100,9 @@
             AVRC_MEDIA_ATTR_ID_GENRE,
             AVRC_MEDIA_ATTR_ID_PLAYING_TIME
             };
-        get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
+        /* Fix for below Klowkwork Issue at line 4996
+         * Array 'attr_list' of size 7 may use index value(s) 7 */
+        get_element_attribute_cmd (sizeof(attr_list)/sizeof(UINT32), attr_list);
     } else {
         BTIF_TRACE_ERROR("%s: Error in get element attr procedure %d",
                          __func__, p_rsp->status);
@@ -3066,12 +5122,12 @@
 {
     bt_bdaddr_t rc_addr;
 
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 
     if (p_rsp->status == AVRC_STS_NO_ERROR)
     {
         HAL_CBACK(bt_rc_ctrl_callbacks, play_position_changed_cb,
-            &rc_addr, p_rsp->song_len, p_rsp->song_pos);
+            &rc_addr, p_rsp->song_len, p_rsp->song_pos, p_rsp->play_status);
     }
     else
     {
@@ -3242,6 +5298,10 @@
 }
 #endif
 
+static void btif_rc_handler_wrapper(UINT16 event, char* p_param)
+{
+    btif_rc_handler((tBTA_AV_EVT)event, (tBTA_AV *)p_param);
+}
 /***************************************************************************
 **
 ** Function         cleanup
@@ -3253,16 +5313,10 @@
 ***************************************************************************/
 static void cleanup()
 {
-    BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
-    close_uinput();
-    if (bt_rc_callbacks)
-    {
-        bt_rc_callbacks = NULL;
-    }
-    alarm_free(btif_rc_cb.rc_play_status_timer);
-    memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
-    lbl_destroy();
-    BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
+    BTIF_TRACE_EVENT("## RC:  %s ##", __FUNCTION__);
+    btif_transfer_context(btif_rc_handler_wrapper, BTIF_AV_CLEANUP_REQ_EVT,
+            NULL, 0, NULL);
+    BTIF_TRACE_EVENT("## RC: %s ## completed", __FUNCTION__);
 }
 
 /***************************************************************************
@@ -3282,7 +5336,7 @@
     {
         bt_rc_ctrl_callbacks = NULL;
     }
-    alarm_free(btif_rc_cb.rc_play_status_timer);
+    alarm_free(btif_rc_cb[0].rc_play_status_timer);
     memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
     lbl_destroy();
     BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
@@ -3320,7 +5374,7 @@
          UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
          BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
                             __FUNCTION__,p_transaction->lbl);
-         BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
+         BTA_AvVendorCmd(btif_rc_cb[0].rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
                                                           data_start, p_msg->len);
          status =  BT_STATUS_SUCCESS;
          start_status_command_timer (AVRC_PDU_GET_CAPABILITIES, p_transaction);
@@ -3368,7 +5422,7 @@
          UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
          BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
                             __FUNCTION__,p_transaction->lbl);
-         BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
+         BTA_AvVendorCmd(btif_rc_cb[0].rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
                                                           data_start, p_msg->len);
          status =  BT_STATUS_SUCCESS;
          start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_ATTR, p_transaction);
@@ -3418,7 +5472,7 @@
          UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
          BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
                             __FUNCTION__,p_transaction->lbl);
-         BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
+         BTA_AvVendorCmd(btif_rc_cb[0].rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
                                data_start, p_msg->len);
          status =  BT_STATUS_SUCCESS;
          start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_VALUES, p_transaction);
@@ -3462,7 +5516,7 @@
      avrc_cmd.get_cur_app_val.num_attr = num_attrib;
      avrc_cmd.get_cur_app_val.pdu = AVRC_PDU_GET_CUR_PLAYER_APP_VALUE;
 
-     for (count = 0; count < num_attrib; count++)
+     for (count = 0; (count < num_attrib) && (count < AVRC_MAX_APP_ATTR_SIZE); count++)
      {
          avrc_cmd.get_cur_app_val.attrs[count] = attrib_ids[count];
      }
@@ -3472,7 +5526,7 @@
          UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
          BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
                             __FUNCTION__,p_transaction->lbl);
-         BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
+         BTA_AvVendorCmd(btif_rc_cb[0].rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
                           data_start, p_msg->len);
          status =  BT_STATUS_SUCCESS;
          start_status_command_timer (AVRC_PDU_GET_CUR_PLAYER_APP_VALUE, p_transaction);
@@ -3529,7 +5583,7 @@
          UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
          BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
                             __FUNCTION__,p_transaction->lbl);
-         BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_CTRL,
+         BTA_AvVendorCmd(btif_rc_cb[0].rc_handle,p_transaction->lbl,AVRC_CMD_CTRL,
                               data_start, p_msg->len);
          status =  BT_STATUS_SUCCESS;
          start_control_command_timer (AVRC_PDU_SET_PLAYER_APP_VALUE, p_transaction);
@@ -3549,63 +5603,6 @@
 
 /***************************************************************************
 **
-** Function         get_player_app_setting_attr_text_cmd
-**
-** Description      Get text description for app attribute
-**
-** Returns          void
-**
-***************************************************************************/
-static bt_status_t get_player_app_setting_attr_text_cmd (UINT8 *attrs, UINT8 num_attrs)
-{
-    tAVRC_STS status = BT_STATUS_UNSUPPORTED;
-    rc_transaction_t *p_transaction = NULL;
-    int count  = 0;
-#if (AVRC_CTLR_INCLUDED == TRUE)
-    tAVRC_COMMAND avrc_cmd = {0};
-    BT_HDR *p_msg = NULL;
-    bt_status_t tran_status;
-    CHECK_RC_CONNECTED
-
-    BTIF_TRACE_DEBUG("%s: num attrs %d", __FUNCTION__, num_attrs);
-
-    tran_status = get_transaction(&p_transaction);
-    if (BT_STATUS_SUCCESS != tran_status)
-        return BT_STATUS_FAIL;
-
-    avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT;
-    avrc_cmd.get_app_attr_txt.opcode = AVRC_OP_VENDOR;
-    avrc_cmd.get_app_attr_txt.num_attr = num_attrs;
-
-    for (count = 0; count < num_attrs; count++)
-    {
-        avrc_cmd.get_app_attr_txt.attrs[count] = attrs[count];
-    }
-    status = AVRC_BldCommand(&avrc_cmd, &p_msg);
-    if (status == AVRC_STS_NO_ERROR)
-    {
-        UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
-                BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
-                __FUNCTION__, p_transaction->lbl);
-        BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
-                AVRC_CMD_STATUS, data_start, p_msg->len);
-        osi_free(p_msg);
-        status =  BT_STATUS_SUCCESS;
-        start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT, p_transaction);
-    }
-    else
-    {
-        BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __FUNCTION__, status);
-    }
-    osi_free(p_msg);
-#else
-    BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
-#endif
-    return status;
-}
-
-/***************************************************************************
-**
 ** Function         get_player_app_setting_val_text_cmd
 **
 ** Description      Get text description for app attribute values
@@ -3646,7 +5643,7 @@
                          __FUNCTION__, p_transaction->lbl);
         if (p_msg != NULL)
         {
-            BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
+            BTA_AvVendorCmd(btif_rc_cb[0].rc_handle, p_transaction->lbl,
                     AVRC_CMD_STATUS, data_start, p_msg->len);
             status =  BT_STATUS_SUCCESS;
             start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT, p_transaction);
@@ -3698,7 +5695,7 @@
                 __FUNCTION__, label);
         if (p_msg != NULL)
         {
-            BTA_AvVendorCmd(btif_rc_cb.rc_handle, label, AVRC_CMD_NOTIF,
+            BTA_AvVendorCmd(btif_rc_cb[0].rc_handle, label, AVRC_CMD_NOTIF,
                     data_start, p_msg->len);
             status =  BT_STATUS_SUCCESS;
         }
@@ -3759,7 +5756,7 @@
                 __FUNCTION__, p_transaction->lbl);
         if (p_msg != NULL)
         {
-            BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
+            BTA_AvVendorCmd(btif_rc_cb[0].rc_handle, p_transaction->lbl,
                     AVRC_CMD_STATUS, data_start, p_msg->len);
             status =  BT_STATUS_SUCCESS;
             start_status_command_timer (AVRC_PDU_GET_ELEMENT_ATTR,
@@ -3813,7 +5810,7 @@
                 __FUNCTION__, p_transaction->lbl);
         if (p_msg != NULL)
         {
-            BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,
+            BTA_AvVendorCmd(btif_rc_cb[0].rc_handle,p_transaction->lbl,
                     AVRC_CMD_STATUS, data_start, p_msg->len);
             status =  BT_STATUS_SUCCESS;
             start_status_command_timer (AVRC_PDU_GET_PLAY_STATUS, p_transaction);
@@ -3855,15 +5852,15 @@
     avrc_rsp.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
     avrc_rsp.volume.status = AVRC_STS_NO_ERROR;
     avrc_rsp.volume.volume = abs_vol;
-    status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
+    status = AVRC_BldResponse(btif_rc_cb[0].rc_handle, &avrc_rsp, &p_msg);
     if (status == AVRC_STS_NO_ERROR)
     {
         UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
         BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
-                __FUNCTION__, btif_rc_cb.rc_vol_label);
+                __FUNCTION__, btif_rc_cb[0].rc_vol_label);
         if (p_msg != NULL)
         {
-            BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
+            BTA_AvVendorRsp(btif_rc_cb[0].rc_handle, label,
                     BTA_AV_RSP_ACCEPT, data_start, p_msg->len, 0);
             status =  BT_STATUS_SUCCESS;
         }
@@ -3905,12 +5902,12 @@
     avrc_rsp.reg_notif.param.volume = abs_vol;
     avrc_rsp.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
 
-    status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
+    status = AVRC_BldResponse(btif_rc_cb[0].rc_handle, &avrc_rsp, &p_msg);
     if (status == AVRC_STS_NO_ERROR) {
         BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
                          __func__, label);
         UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
-        BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
+        BTA_AvVendorRsp(btif_rc_cb[0].rc_handle, label,
                         (rsp_type == BTRC_NOTIFICATION_TYPE_INTERIM) ?
                             AVRC_RSP_INTERIM : AVRC_RSP_CHANGED,
                         data_start, p_msg->len, 0);
@@ -3945,7 +5942,7 @@
     BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
                                                     key_code, key_state);
     CHECK_RC_CONNECTED
-    if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
+    if (btif_rc_cb[0].rc_features & BTA_AV_FEAT_RCTG)
     {
         bt_status_t tran_status = get_transaction(&p_transaction);
         if ((BT_STATUS_SUCCESS == tran_status) && (NULL != p_transaction)) {
@@ -3954,7 +5951,7 @@
              UINT24_TO_BE_STREAM(start, AVRC_CO_METADATA);
              *(start)++ = 0;
              UINT8_TO_BE_STREAM(start, key_code);
-             BTA_AvRemoteVendorUniqueCmd(btif_rc_cb.rc_handle,
+             BTA_AvRemoteVendorUniqueCmd(btif_rc_cb[0].rc_handle,
                                          p_transaction->lbl,
                                          (tBTA_AV_STATE)key_state, buffer,
                                          AVRC_PASS_THRU_GROUP_LEN);
@@ -3991,17 +5988,22 @@
 static bt_status_t send_passthrough_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code, uint8_t key_state)
 {
     tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+    /* Controller is used only for Certification purposes.
+     * In normal case AVRCP controller will not be used, hence
+     * updating this is required.
+     */
+    int index = BTIF_RC_DEFAULT_INDEX; //For RC it should be 0
 #if (AVRC_CTLR_INCLUDED == TRUE)
     CHECK_RC_CONNECTED
     rc_transaction_t *p_transaction=NULL;
     BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
                                                     key_code, key_state);
-    if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
+    if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG)
     {
         bt_status_t tran_status = get_transaction(&p_transaction);
         if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction)
         {
-            BTA_AvRemoteCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
+            BTA_AvRemoteCmd(btif_rc_cb[index].rc_handle, p_transaction->lbl,
                 (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
             status =  BT_STATUS_SUCCESS;
             BTIF_TRACE_DEBUG("%s: succesfully sent passthrough command to BTA", __FUNCTION__);
@@ -4027,15 +6029,23 @@
     sizeof(bt_rc_interface),
     init,
     get_play_status_rsp,
-    NULL, /* list_player_app_attr_rsp */
-    NULL, /* list_player_app_value_rsp */
-    NULL, /* get_player_app_value_rsp */
-    NULL, /* get_player_app_attr_text_rsp */
-    NULL, /* get_player_app_value_text_rsp */
+    list_player_app_attr_rsp,     /* list_player_app_attr_rsp */
+    list_player_app_value_rsp,    /* list_player_app_value_rsp */
+    get_player_app_value_rsp,     /* get_player_app_value_rsp PDU 0x13*/
+    get_player_app_attr_text_rsp, /* get_player_app_attr_text_rsp */
+    get_player_app_value_text_rsp,/* get_player_app_value_text_rsp */
     get_element_attr_rsp,
-    NULL, /* set_player_app_value_rsp */
+    set_player_app_value_rsp,     /* set_player_app_value_rsp */
     register_notification_rsp,
     set_volume,
+    get_folderitem_rsp,
+    set_addrplayer_rsp,
+    set_browseplayer_rsp,
+    changepath_rsp,
+    playitem_rsp,
+    get_itemattr_rsp,
+    is_device_active_in_handoff,
+    get_total_items_rsp,
     cleanup,
 };
 
@@ -4230,7 +6240,11 @@
 *******************************************************************************/
 void lbl_destroy()
 {
-    pthread_mutex_destroy(&(device.lbllock));
+    if (!pthread_mutex_destroy(&(device.lbllock)))
+    {
+        device.lbllock_destroyed = TRUE;
+        BTIF_TRACE_EVENT(" %s: lbllock destroy success ", __FUNCTION__);
+    }
 }
 
 /*******************************************************************************
diff --git a/btif/src/btif_rfcomm.c b/btif/src/btif_rfcomm.c
new file mode 100644
index 0000000..9d799c8
--- /dev/null
+++ b/btif/src/btif_rfcomm.c
@@ -0,0 +1,247 @@
+/*
+ *Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the followin conditions are met:
+ *        * Redistributions of source code must retain the above copyright
+ *          notice, this list of conditions and the followin disclaimer.
+ *        * Redistributions in binary form must reproduce the above copyriht
+ *            notice, this list of conditions and the followin disclaimer in the
+ *            documentation and/or other materials provided with the distribution.
+ *        * Neither the name of The Linux Foundation nor
+ *            the names of its contributors may be used to endorse or promote
+ *            products derived from this software without specific prior written
+ *            permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.    IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <hardware/bluetooth.h>
+#include "port_api.h"
+#include "btm_api.h"
+#include "btu.h"
+#include "btm_api.h"
+#include "bt_testapp.h"
+#define LOG_NDDEBUG 0
+#define LOG_TAG "bluedroid"
+#include "btif_api.h"
+#include "bt_utils.h"
+
+/************************************************************************************
+**  Constants & Macros
+************************************************************************************/
+#define RFC_BUFFER_SIZE  20000
+
+/************************************************************************************
+**  Externs
+************************************************************************************/
+static void bt_rfc_mmt_cback (UINT32 code, UINT16 handle); //rfc
+static void bt_rfc_mmt_cback_msc_data (UINT32 code, UINT16 handle);
+static void bt_rfc_mmt_server_cback (UINT32 code, UINT16 handle);//rfc
+static int bt_rfc_data_cback (UINT16 port_handle, void *data, UINT16 len);//rfc
+static void bt_rfc_port_cback (UINT32 code, UINT16 handle);//rfc
+void rdut_rfcomm (UINT8 server);
+void rdut_rfcomm_test_interface (tRFC *input);
+static UINT16 rfc_handle = 0;
+char buffer[RFC_BUFFER_SIZE];
+
+/************************************************************************************
+**  Functions
+************************************************************************************/
+static const btrfcomm_interface_t btrfcInterface = {
+    sizeof(btrfcomm_interface_t),
+    NULL,
+    rdut_rfcomm,
+    rdut_rfcomm_test_interface,
+    NULL,
+    NULL,
+};
+
+const btrfcomm_interface_t *btif_rfcomm_get_interface(void)
+{
+    BTIF_TRACE_EVENT("%s", __FUNCTION__);
+    ALOGI("\n%s\n", __FUNCTION__);
+    return &btrfcInterface;
+}
+
+static void bt_rfc_mmt_cback (UINT32 code, UINT16 handle)
+{
+    UINT16   length = 0;
+    int      count  = 100;//Number of frames to be send
+
+    ALOGI("dut_rfc_mmt_cback %d, %x", code, handle);
+    memset(buffer , 0x01 ,10000); //RFC data
+    if (code == PORT_SUCCESS)
+    {
+        PORT_WriteData (handle, buffer, 10000, &length);
+        --count;
+        ALOGI("rfc mmt length: %d", length);
+    }
+}
+
+static void bt_rfc_mmt_cback_msc_data (UINT32 code, UINT16 handle)
+{
+    ALOGI("dut_rfc_mmt_cback_msc_data %d, %x", code, handle);
+}
+
+static void bt_rfc_send_data ( UINT16 handle)
+{
+    UINT16   length = 0;
+
+    ALOGI("bt_rfc_send_data %d", handle);
+    memset(buffer , 0x01 ,10000); //RFC data
+    PORT_WriteData (handle, buffer, 10000, &length);
+}
+
+static void bt_rfc_mmt_server_cback (UINT32 code, UINT16 handle)
+{
+    ALOGI("dut_rfc_mmt_Server_cback %d, %x", code, handle);
+}
+
+
+static int bt_rfc_data_cback (UINT16 port_handle, void *data, UINT16 len)
+{
+    ALOGI("dut_rfc_data_cback"); // Called from PORT_DataInd
+    return 0;
+}
+
+static void bt_rfc_port_cback (UINT32 code, UINT16 handle)
+{
+    ALOGI("bt_rfc_port_cback");
+}
+
+/*static void bdcpy (BD_ADDR a, const BD_ADDR b)
+{
+    int   i;
+    for (i = BD_ADDR_LEN; i != 0; i--)
+    {
+        *a++ = *b++;
+    }
+} */
+
+
+
+void rdut_rfcomm (UINT8 server)
+{
+    UINT16   handle;
+    int status = -1;
+    BD_ADDR remote_bd = {0x00, 0x15, 0x83, 0x0A, 0x0E, 0x1F};
+    BD_ADDR any_add   = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+    ALOGI("dut_rfc_mode:%d",server);
+    if (server == 0)
+    {
+        BTM_SetSecurityLevel (TRUE, "", 0, 0, 0x03, 3/*BTM_SEC_PROTO_RFCOMM*/, 20);
+        status = RFCOMM_CreateConnection(0x0020, 20, FALSE, 256, (UINT8 *)remote_bd,
+                                            &handle, bt_rfc_mmt_cback);
+        rfc_handle = handle;
+    }
+    else if (server == 1)
+    {
+        BTM_SetSecurityLevel (FALSE, "", 0, 0, 0x03, 3/*BTM_SEC_PROTO_RFCOMM */, 20);
+        BTM_SetConnectability (1, 0, 0); //Pae Mode , window , interval
+        status = RFCOMM_CreateConnection (0x0020, 20, TRUE, 256, (UINT8 *)any_add,
+                                       &handle, bt_rfc_mmt_server_cback);
+        rfc_handle = handle;
+    }
+    else if (server == 3)
+    {
+        ALOGI("dut RFCOMM RemoveConnection");
+        RFCOMM_RemoveConnection(rfc_handle);
+    }
+    if (status == PORT_SUCCESS)
+    {
+        ALOGI("dut_setdata_callback");
+        PORT_SetDataCallback (handle, bt_rfc_data_cback);
+        PORT_SetEventCallback(handle, bt_rfc_port_cback);
+    }
+}
+
+void rdut_rfcomm_test_interface (tRFC *input)
+{
+    BD_ADDR   remote_bd;
+    UINT16    handle;
+    int status = -1;
+    BD_ADDR any_add   = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+    switch (input->param)
+    {
+        case RFC_TEST_CLIENT:
+        {
+            bdcpy (remote_bd, input->data.conn.bdadd.address);
+            BTM_SetSecurityLevel (TRUE, "", 0, 0, 0x03, 3/*BTM_SEC_PROTO_RFCOMM */,
+                                                                   input->data.conn.scn);
+            status = RFCOMM_CreateConnection(0x0020, input->data.conn.scn, FALSE, 256,
+                                                 (UINT8 *)remote_bd,&handle, bt_rfc_mmt_cback);
+            rfc_handle = handle;
+        }
+        break;
+        case RFC_TEST_CLIENT_TEST_MSC_DATA:
+        {
+            bdcpy (remote_bd, input->data.conn.bdadd.address);
+            BTM_SetSecurityLevel (TRUE, "", 0, 0, 0x03, 3/*BTM_SEC_PROTO_RFCOMM */,
+                                                                input->data.conn.scn);
+            status = RFCOMM_CreateConnection(0x0020, input->data.conn.scn, FALSE, 256,
+                                       (UINT8 *)remote_bd, &handle, bt_rfc_mmt_cback_msc_data);
+            rfc_handle = handle;
+        }
+        break;
+        case RFC_TEST_FRAME_ERROR:
+        {
+             /* Framing Error */
+             PORT_SendError (rfc_handle, 0x08);
+        }
+        break;
+        case RFC_TEST_ROLE_SWITCH:
+        {
+            /* Role Switch */
+            BTM_SwitchRole(input->data.role_switch.bdadd.address, input->data.role_switch.role,
+                                                                                         NULL);
+        }
+        break;
+        case RFC_TEST_SERVER:
+        {
+            BTM_SetSecurityLevel (FALSE, "", 0, 0, 0x03, 3/*BTM_SEC_PROTO_RFCOMM */, 20);
+            BTM_SetConnectability (1, 0, 0); //Pae Mode , window , interval
+            status = RFCOMM_CreateConnection (0x0020, 20, TRUE, 256, (UINT8 *)any_add,
+                                               &handle, bt_rfc_mmt_server_cback);
+            rfc_handle = handle;
+        }
+        break;
+        case RFC_TEST_DISCON:
+        {
+            ALOGI("dut RFCOMM RemoveConnection");
+            RFCOMM_RemoveConnection(rfc_handle);
+        }
+        break;
+        case RFC_TEST_WRITE_DATA:
+        {
+            ALOGI("dut RFC_TEST_WRITE_DATA");
+            bt_rfc_send_data(rfc_handle);
+        }
+        break;
+        default :
+            ALOGI("dut RFCOMM Unreconised command");
+        break;
+    }
+    if (status == PORT_SUCCESS)
+    {
+        ALOGI("dut_setdata_callback");
+        PORT_SetDataCallback (handle, bt_rfc_data_cback);
+        PORT_SetEventCallback(handle, bt_rfc_port_cback);
+    }
+}
diff --git a/btif/src/btif_sdp_server.c b/btif/src/btif_sdp_server.c
index 90d74cf..7ecaa33 100644
--- a/btif/src/btif_sdp_server.c
+++ b/btif/src/btif_sdp_server.c
@@ -41,6 +41,7 @@
 #include "btif_util.h"
 #include "osi/include/allocator.h"
 #include "utl.h"
+#include "stack_manager.h"
 
 static pthread_mutex_t sdp_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
 
@@ -243,6 +244,8 @@
 /***
  * Use this to get a reference to a SDP slot AND change the state to
  * SDP_RECORD_CREATE_INITIATED.
+ *
+ * Caller of this function should held mutex with sdp_lock
  */
 static const sdp_slot_t* start_create_sdp(int id) {
     sdp_slot_t* sdp_slot;
@@ -250,14 +253,12 @@
         APPL_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id);
         return NULL;
     }
-    pthread_mutex_lock(&sdp_lock);
     if(sdp_slots[id].state == SDP_RECORD_ALLOCED) {
         sdp_slot = &(sdp_slots[id]);
     } else {
         /* The record have been removed before this event occurred - e.g. deinit */
         sdp_slot = NULL;
     }
-    pthread_mutex_unlock(&sdp_lock);
     if(sdp_slot == NULL) {
         APPL_TRACE_ERROR("%s() failed - state for id %d is "
                 "sdp_slots[id].state = %d expected %d", __func__,
@@ -265,11 +266,11 @@
     }
     return sdp_slot;
 }
-
+/***
+ * Caller of this function should held mutex with sdp_lock
+ */
 static void set_sdp_handle(int id, int handle) {
-    pthread_mutex_lock(&sdp_lock);
     sdp_slots[id].sdp_handle = handle;
-    pthread_mutex_unlock(&sdp_lock);
     BTIF_TRACE_DEBUG("%s() id=%d to handle=0x%08x", __FUNCTION__, id, handle);
 }
 
@@ -292,6 +293,11 @@
 bt_status_t remove_sdp_record(int record_id) {
     int handle;
 
+    if (!stack_manager_get_interface()->get_stack_is_running()) {
+        BTIF_TRACE_DEBUG("Sdp Server %s - Stack closed", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+
     /* Get the Record handle, and free the slot */
     handle = free_sdp_slot(record_id);
     BTIF_TRACE_DEBUG("Sdp Server %s id=%d to handle=0x%08x",
@@ -319,6 +325,7 @@
      * 4) What to do at fail?
      * */
     BTIF_TRACE_DEBUG("Sdp Server %s", __FUNCTION__);
+    pthread_mutex_lock(&sdp_lock);
     const sdp_slot_t* sdp_slot = start_create_sdp(id);
     /* In the case we are shutting down, sdp_slot is NULL */
     if(sdp_slot != NULL) {
@@ -350,6 +357,7 @@
             set_sdp_handle(id, handle);
         }
     }
+    pthread_mutex_unlock(&sdp_lock);
 }
 
 void on_remove_record_event(int handle) {
diff --git a/btif/src/btif_sm.c b/btif/src/btif_sm.c
index aa856c5..08bcba2 100644
--- a/btif/src/btif_sm.c
+++ b/btif/src/btif_sm.c
@@ -37,6 +37,7 @@
 ******************************************************************************/
 typedef struct {
     btif_sm_state_t         state;
+    int                     index;
     btif_sm_handler_t       *p_handlers;
 } btif_sm_cb_t;
 
@@ -57,7 +58,8 @@
 **
 ******************************************************************************/
 
-btif_sm_handle_t btif_sm_init(const btif_sm_handler_t *p_handlers, btif_sm_state_t initial_state)
+btif_sm_handle_t btif_sm_init(const btif_sm_handler_t *p_handlers, btif_sm_state_t initial_state,
+                            int index)
 {
     if (p_handlers == NULL) {
         BTIF_TRACE_ERROR("%s : p_handlers is NULL", __FUNCTION__);
@@ -67,9 +69,10 @@
     btif_sm_cb_t *p_cb = (btif_sm_cb_t *)osi_malloc(sizeof(btif_sm_cb_t));
     p_cb->state = initial_state;
     p_cb->p_handlers = (btif_sm_handler_t*)p_handlers;
+    p_cb->index = index;
 
     /* Send BTIF_SM_ENTER_EVT to the initial state */
-    p_cb->p_handlers[initial_state](BTIF_SM_ENTER_EVT, NULL);
+    p_cb->p_handlers[initial_state](BTIF_SM_ENTER_EVT, NULL, index);
 
     return (btif_sm_handle_t)p_cb;
 }
@@ -107,7 +110,6 @@
 btif_sm_state_t btif_sm_get_state(btif_sm_handle_t handle)
 {
     btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle;
-
     if (p_cb == NULL)
     {
         BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__);
@@ -141,7 +143,7 @@
         return BT_STATUS_FAIL;
     }
 
-    if (p_cb->p_handlers[p_cb->state](event, data) == FALSE)
+    if (p_cb->p_handlers[p_cb->state](event, data, p_cb->index) == FALSE)
         return BT_STATUS_UNHANDLED;
 
     return status;
@@ -172,14 +174,14 @@
     }
 
     /* Send exit event to the current state */
-    if (p_cb->p_handlers[p_cb->state](BTIF_SM_EXIT_EVT, NULL) == FALSE)
+    if (p_cb->p_handlers[p_cb->state](BTIF_SM_EXIT_EVT, NULL, p_cb->index) == FALSE)
         status = BT_STATUS_UNHANDLED;
 
     /* Change to the new state */
     p_cb->state = state;
 
     /* Send enter event to the new state */
-    if (p_cb->p_handlers[p_cb->state](BTIF_SM_ENTER_EVT, NULL) == FALSE)
+    if (p_cb->p_handlers[p_cb->state](BTIF_SM_ENTER_EVT, NULL, p_cb->index) == FALSE)
         status = BT_STATUS_UNHANDLED;
 
     return status;
diff --git a/btif/src/btif_smp.c b/btif/src/btif_smp.c
new file mode 100644
index 0000000..03f6473
--- /dev/null
+++ b/btif/src/btif_smp.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <hardware/bluetooth.h>
+
+
+#define LOG_NDDEBUG 0
+#define LOG_TAG "bluedroid"
+
+#include "btif_api.h"
+#include "bt_utils.h"
+#include "smp_api.h"
+
+#ifdef TEST_APP_INTERFACE
+#include <bt_testapp.h>
+static void SmpInit(void)
+{
+    SMP_Init();
+}
+static BOOLEAN SmpRegister(tSMP_CALLBACK *p_cback)
+{
+    BOOLEAN Ret = 0;
+    Ret = SMP_Register(p_cback);
+    printf("%s:: Ret=%d\n", __FUNCTION__, Ret);
+    return Ret;
+
+}
+
+static tSMP_STATUS SmpPair(BD_ADDR bd_addr)
+{
+    tSMP_STATUS Ret = 0;
+    Ret = SMP_Pair(bd_addr);
+    printf("%s:: Ret=%d\n", __FUNCTION__, Ret);
+    return Ret;
+}
+
+static BOOLEAN PairCancel(BD_ADDR bd_addr)
+{
+    BOOLEAN Ret = 0;
+    Ret = SMP_PairCancel(bd_addr);
+    printf("%s:: Ret=%d\n", __FUNCTION__, Ret);
+    return Ret;
+}
+
+static void SecurityGrant(BD_ADDR bd_addr, UINT8 res)
+{
+        SMP_SecurityGrant(bd_addr, res);
+    printf("%s:: executed \n", __FUNCTION__);
+}
+
+static void PasskeyReply(BD_ADDR bd_addr, UINT8 res, UINT32 passkey)
+{
+        SMP_PasskeyReply(bd_addr, res, passkey);
+    printf("%s:: executed \n", __FUNCTION__);
+}
+
+static BOOLEAN Encrypt(UINT8 *key, UINT8 key_len,
+                                        UINT8 *plain_text, UINT8 pt_len,
+                                        tSMP_ENC *p_out)
+{
+    BOOLEAN Ret = 0;
+    Ret = SMP_Encrypt(key, key_len, plain_text, pt_len, p_out);
+    printf("%s:: Ret=%d\n", __FUNCTION__, Ret);
+    return Ret;
+}
+
+static const btsmp_interface_t btsmpInterface = {
+    sizeof(btsmp_interface_t),
+    SmpInit,
+    SmpRegister,
+    SmpPair,
+    PairCancel,
+    SecurityGrant,
+    PasskeyReply,
+    Encrypt
+};
+
+const btsmp_interface_t *btif_smp_get_interface(void)
+{
+    BTIF_TRACE_EVENT("%s", __FUNCTION__);
+    printf("\n%s\n", __FUNCTION__);
+    return &btsmpInterface;
+}
+
+#endif   //TEST_APP_INTERFACE
diff --git a/btif/src/btif_sock.c b/btif/src/btif_sock.c
index 3b43545..7acbcbe 100644
--- a/btif/src/btif_sock.c
+++ b/btif/src/btif_sock.c
@@ -37,6 +37,10 @@
 static bt_status_t btsock_listen(btsock_type_t type, const char *service_name, const uint8_t *uuid, int channel, int *sock_fd, int flags, int app_uid);
 static bt_status_t btsock_connect(const bt_bdaddr_t *bd_addr, btsock_type_t type, const uint8_t *uuid, int channel, int *sock_fd, int flags, int app_uid);
 
+static bt_status_t btsock_get_sockopt(btsock_type_t type, int channel, btsock_option_type_t option_name,
+                                            void *option_value, int *option_len);
+static bt_status_t btsock_set_sockopt(btsock_type_t type, int channel, btsock_option_type_t option_name,
+                                            void *option_value, int option_len);
 static void btsock_signaled(int fd, int type, int flags, uint32_t user_id);
 
 static int thread_handle = -1;
@@ -46,10 +50,11 @@
   static btsock_interface_t interface = {
     sizeof(interface),
     btsock_listen,
-    btsock_connect
+    btsock_connect,
+    btsock_get_sockopt,
+    btsock_set_sockopt
   };
 
-
   return &interface;
 }
 
@@ -175,6 +180,69 @@
   return status;
 }
 
+static bt_status_t btsock_get_sockopt(btsock_type_t type, int channel, btsock_option_type_t option_name,
+                                            void *option_value, int *option_len)
+{
+    if((channel <= 0) || (option_value == NULL) || (option_len == NULL))
+    {
+        BTIF_TRACE_ERROR("invalid parameters, channel:%d, option_value:%p, option_len:%p", channel,
+                                                                        option_value, option_len);
+        return BT_STATUS_PARM_INVALID;
+    }
+
+    bt_status_t status = BT_STATUS_FAIL;
+    switch(type)
+    {
+        case BTSOCK_RFCOMM:
+            status = btsock_rfc_get_sockopt(channel, option_name, option_value, option_len);
+            break;
+        case BTSOCK_L2CAP:
+            BTIF_TRACE_ERROR("bt l2cap socket type not supported, type:%d", type);
+            status = BT_STATUS_UNSUPPORTED;
+            break;
+        case BTSOCK_SCO:
+            BTIF_TRACE_ERROR("bt sco socket not supported, type:%d", type);
+            status = BT_STATUS_UNSUPPORTED;
+            break;
+        default:
+            BTIF_TRACE_ERROR("unknown bt socket type:%d", type);
+            status = BT_STATUS_UNSUPPORTED;
+            break;
+    }
+    return status;
+}
+
+static bt_status_t btsock_set_sockopt(btsock_type_t type, int channel, btsock_option_type_t option_name,
+                                            void *option_value, int option_len)
+{
+    if((channel <= 0) || (option_value == NULL))
+    {
+        BTIF_TRACE_ERROR("invalid parameters, channel:%d, option_value:%p", channel, option_value);
+        return BT_STATUS_PARM_INVALID;
+    }
+
+    bt_status_t status = BT_STATUS_FAIL;
+    switch(type)
+    {
+        case BTSOCK_RFCOMM:
+            status = btsock_rfc_set_sockopt(channel, option_name, option_value, option_len);
+            break;
+        case BTSOCK_L2CAP:
+            BTIF_TRACE_ERROR("bt l2cap socket type not supported, type:%d", type);
+            status = BT_STATUS_UNSUPPORTED;
+            break;
+        case BTSOCK_SCO:
+            BTIF_TRACE_ERROR("bt sco socket not supported, type:%d", type);
+            status = BT_STATUS_UNSUPPORTED;
+            break;
+        default:
+            BTIF_TRACE_ERROR("unknown bt socket type:%d", type);
+            status = BT_STATUS_UNSUPPORTED;
+            break;
+    }
+    return status;
+}
+
 static void btsock_signaled(int fd, int type, int flags, uint32_t user_id) {
   switch (type) {
     case BTSOCK_RFCOMM:
diff --git a/btif/src/btif_sock_l2cap.c b/btif/src/btif_sock_l2cap.c
index 03c3ef4..4d830ad 100644
--- a/btif/src/btif_sock_l2cap.c
+++ b/btif/src/btif_sock_l2cap.c
@@ -90,7 +90,7 @@
 
 static bt_status_t btSock_start_l2cap_server_l(l2cap_socket *sock);
 
-static pthread_mutex_t state_lock;
+static pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER;
 
 l2cap_socket *socks = NULL;
 static uid_set_t* uid_set = NULL;
@@ -276,7 +276,7 @@
     else
     {
         // Only call if we are non server connections
-        if (sock->handle && (sock->server == FALSE)) {
+        if ((sock->handle >= 0) && (sock->server == FALSE)) {
             if (sock->fixed_chan)
                 BTA_JvL2capCloseLE(sock->handle);
             else
@@ -287,6 +287,11 @@
                 BTA_JvFreeChannel(sock->channel, BTA_JV_CONN_TYPE_L2CAP_LE);
             else
                 BTA_JvFreeChannel(sock->channel, BTA_JV_CONN_TYPE_L2CAP);
+
+            if (!sock->fixed_chan) {
+                APPL_TRACE_DEBUG("%s stopping L2CAP server channel %d", __func__, sock->channel);
+                BTA_JvL2capStopServer(sock->channel, UINT_TO_PTR(sock->id));
+            }
         }
     }
 
@@ -362,7 +367,6 @@
 bt_status_t btsock_l2cap_init(int handle, uid_set_t* set)
 {
     APPL_TRACE_DEBUG("%s handle = %d", __func__);
-    pthread_mutex_init(&state_lock, NULL);
     pthread_mutex_lock(&state_lock);
     pth = handle;
     socks = NULL;
@@ -379,7 +383,6 @@
     while (socks)
         btsock_l2cap_free_l(socks);
     pthread_mutex_unlock(&state_lock);
-    pthread_mutex_destroy(&state_lock);
 
     return BT_STATUS_SUCCESS;
 }
@@ -466,20 +469,24 @@
 
     // Mutex locked by caller
     accept_rs = btsock_l2cap_alloc_l(sock->name, (const bt_bdaddr_t*)p_open->rem_bda, FALSE, 0);
-    accept_rs->connected = TRUE;
-    accept_rs->security = sock->security;
-    accept_rs->fixed_chan = sock->fixed_chan;
-    accept_rs->channel = sock->channel;
-    accept_rs->handle = sock->handle;
-    accept_rs->app_uid = sock->app_uid;
-    sock->handle = -1; /* We should no longer associate this handle with the server socket */
-    accept_rs->is_le_coc = sock->is_le_coc;
+    if (accept_rs) {
+        accept_rs->connected = TRUE;
+        accept_rs->security = sock->security;
+        accept_rs->fixed_chan = sock->fixed_chan;
+        accept_rs->channel = sock->channel;
+        accept_rs->handle = sock->handle;
+        accept_rs->app_uid = sock->app_uid;
+        sock->handle = -1; /* We should no longer associate this handle with the server socket */
+        accept_rs->is_le_coc = sock->is_le_coc;
 
     /* Swap IDs to hand over the GAP connection to the accepted socket, and start a new server on
        the newly create socket ID. */
-    new_listen_id = accept_rs->id;
-    accept_rs->id = sock->id;
-    sock->id = new_listen_id;
+        new_listen_id = accept_rs->id;
+        accept_rs->id = sock->id;
+        sock->id = new_listen_id;
+    } else {
+        APPL_TRACE_ERROR("Memory not allocated for accept_rs..");
+    }
 
     if (accept_rs) {
         //start monitor the socket
@@ -822,19 +829,21 @@
  * and this function is called with the newly allocated PSM.
  */
 void on_l2cap_psm_assigned(int id, int psm) {
-    l2cap_socket *sock;
     /* Setup ETM settings:
      *  mtu will be set below */
     pthread_mutex_lock(&state_lock);
-    sock = btsock_l2cap_find_by_id_l(id);
-    sock->channel = psm;
+    l2cap_socket *sock = btsock_l2cap_find_by_id_l(id);
 
-    if(btSock_start_l2cap_server_l(sock) != BT_STATUS_SUCCESS) {
-        btsock_l2cap_free_l(sock);
+    if (sock) {
+        sock->channel = psm;
+
+        if (btSock_start_l2cap_server_l(sock) != BT_STATUS_SUCCESS)
+            btsock_l2cap_free_l(sock);
+    } else {
+        APPL_TRACE_ERROR("%s: Error: sock is null", __func__);
     }
 
     pthread_mutex_unlock(&state_lock);
-
 }
 
 static bt_status_t btSock_start_l2cap_server_l(l2cap_socket *sock) {
diff --git a/btif/src/btif_sock_rfc.c b/btif/src/btif_sock_rfc.c
index 0a971fd..dc014f0 100644
--- a/btif/src/btif_sock_rfc.c
+++ b/btif/src/btif_sock_rfc.c
@@ -57,6 +57,10 @@
  * L2CAP functions from this file. */
 #include "btif_sock_l2cap.h"
 
+#define MODEM_SIGNAL_DTRDSR        0x01
+#define MODEM_SIGNAL_RTSCTS        0x02
+#define MODEM_SIGNAL_RI            0x04
+#define MODEM_SIGNAL_DCD           0x08
 #define MAX_RFC_CHANNEL 30  // Maximum number of RFCOMM channels (1-30 inclusive).
 #define MAX_RFC_SESSION 7   // Maximum number of devices we can have an RFCOMM connection with.
 
@@ -128,7 +132,6 @@
 
 void btsock_rfc_cleanup(void) {
   pth = -1;
-  uid_set = NULL;
 
   pthread_mutex_lock(&slot_lock);
   for (size_t i = 0; i < ARRAY_SIZE(rfc_slots); ++i) {
@@ -170,6 +173,27 @@
   return (slot == -1) ? NULL : &rfc_slots[slot];
 }
 
+static rfc_slot_t* find_rfc_slot_by_scn(int scn)
+{
+    int i;
+    if(scn > 0)
+    {
+        /* traverse it from the last entry, as incase of
+         * server two entries will exist with the same scn
+         * and the later entry is valid
+         */
+        for(i = MAX_RFC_CHANNEL-1; i >= 0; i--)
+        {
+            if(rfc_slots[i].scn == scn)
+            {
+                if(rfc_slots[i].id)
+                    return &rfc_slots[i];
+            }
+        }
+    }
+    return NULL;
+}
+
 static bool is_requesting_sdp(void) {
   for (size_t i = 0; i < ARRAY_SIZE(rfc_slots); ++i)
     if (rfc_slots[i].id && rfc_slots[i].f.doing_sdp_request)
@@ -375,6 +399,96 @@
   return status;
 }
 
+bt_status_t btsock_rfc_get_sockopt(int channel, btsock_option_type_t option_name,
+                                            void *option_value, int *option_len)
+{
+    int status = BT_STATUS_FAIL;
+
+    APPL_TRACE_DEBUG("btsock_rfc_get_sockopt channel is %d ", channel);
+    if((channel < 1) || (channel > 30) || (option_value == NULL) || (option_len == NULL))
+    {
+        APPL_TRACE_ERROR("invalid rfc channel:%d or option_value:%p, option_len:%p",
+                                             channel, option_value, option_len);
+        return BT_STATUS_PARM_INVALID;
+    }
+    rfc_slot_t* rs = find_rfc_slot_by_scn(channel);
+    if((rs) && ((option_name == BTSOCK_OPT_GET_MODEM_BITS)))
+    {
+        if(PORT_SUCCESS == PORT_GetModemStatus(rs->rfc_port_handle, (UINT8 *)option_value))
+        {
+            *option_len = sizeof(UINT8);
+            status = BT_STATUS_SUCCESS;
+        }
+    }
+    return status;
+}
+
+bt_status_t btsock_rfc_set_sockopt(int channel, btsock_option_type_t option_name,
+                                            void *option_value, int option_len)
+{
+    int status = BT_STATUS_FAIL;
+
+    APPL_TRACE_DEBUG("btsock_rfc_get_sockopt channel is %d ", channel);
+    if((channel < 1) || (channel > 30) || (option_value == NULL) || (option_len <= 0)
+                     || (option_len > (int)sizeof(UINT8)))
+    {
+        APPL_TRACE_ERROR("invalid rfc channel:%d or option_value:%p, option_len:%d",
+                                        channel, option_value, option_len);
+        return BT_STATUS_PARM_INVALID;
+    }
+    rfc_slot_t* rs = find_rfc_slot_by_scn(channel);
+    if((rs) && ((option_name == BTSOCK_OPT_SET_MODEM_BITS)))
+    {
+        if((*((UINT8 *)option_value)) & MODEM_SIGNAL_DTRDSR)
+        {
+            if(PORT_SUCCESS != PORT_Control(rs->rfc_port_handle, PORT_SET_DTRDSR))
+                return status;
+        }
+        if((*((UINT8 *)option_value)) & MODEM_SIGNAL_RTSCTS)
+        {
+            if(PORT_SUCCESS != PORT_Control(rs->rfc_port_handle, PORT_SET_CTSRTS))
+                return status;
+        }
+        if((*((UINT8 *)option_value)) & MODEM_SIGNAL_RI)
+        {
+            if(PORT_SUCCESS != PORT_Control(rs->rfc_port_handle, PORT_SET_RI))
+                return status;
+        }
+        if((*((UINT8 *)option_value)) & MODEM_SIGNAL_DCD)
+        {
+            if(PORT_SUCCESS != PORT_Control(rs->rfc_port_handle, PORT_SET_DCD))
+                return status;
+        }
+        status = BT_STATUS_SUCCESS;
+    }
+    else if((rs) && ((option_name == BTSOCK_OPT_CLR_MODEM_BITS)))
+    {
+        if((*((UINT8 *)option_value)) & MODEM_SIGNAL_DTRDSR)
+        {
+            if(PORT_SUCCESS != PORT_Control(rs->rfc_port_handle, PORT_CLR_DTRDSR))
+                return status;
+        }
+        if((*((UINT8 *)option_value)) & MODEM_SIGNAL_RTSCTS)
+        {
+            if(PORT_SUCCESS != PORT_Control(rs->rfc_port_handle, PORT_CLR_CTSRTS))
+                return status;
+        }
+        if((*((UINT8 *)option_value)) & MODEM_SIGNAL_RI)
+        {
+            if(PORT_SUCCESS != PORT_Control(rs->rfc_port_handle, PORT_CLR_RI))
+                return status;
+        }
+        if((*((UINT8 *)option_value)) & MODEM_SIGNAL_DCD)
+        {
+            if(PORT_SUCCESS != PORT_Control(rs->rfc_port_handle, PORT_CLR_DCD))
+                return status;
+        }
+        status = BT_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
 static int create_server_sdp_record(rfc_slot_t *slot) {
     if(slot->scn == 0) {
         return false;
@@ -437,13 +551,15 @@
   return sock_send_all(slot->fd, (const uint8_t*)&slot->scn, sizeof(slot->scn)) == sizeof(slot->scn);
 }
 
-static bool send_app_connect_signal(int fd, const bt_bdaddr_t* addr, int channel, int status, int send_fd) {
+static bool send_app_connect_signal(int fd, const bt_bdaddr_t* addr, int channel, int status,
+                                    int send_fd, int tx_mtu)
+{
   sock_connect_signal_t cs;
   cs.size = sizeof(cs);
   cs.bd_addr = *addr;
   cs.channel = channel;
   cs.status = status;
-  cs.max_rx_packet_size = 0; // not used for RFCOMM
+  cs.max_rx_packet_size = tx_mtu;
   cs.max_tx_packet_size = 0; // not used for RFCOMM
   if (send_fd == INVALID_FD)
     return sock_send_all(fd, (const uint8_t *)&cs, sizeof(cs)) == sizeof(cs);
@@ -498,7 +614,8 @@
   // Start monitoring the socket.
   btsock_thread_add_fd(pth, srv_rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_EXCEPTION, srv_rs->id);
   btsock_thread_add_fd(pth, accept_rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_RD, accept_rs->id);
-  send_app_connect_signal(srv_rs->fd, &accept_rs->addr, srv_rs->scn, 0, accept_rs->app_fd);
+  LOG_DEBUG(LOG_TAG, "%s  mtu = %d ", __func__,p_open->mtu);
+  send_app_connect_signal(srv_rs->fd, &accept_rs->addr, srv_rs->scn, 0, accept_rs->app_fd, p_open->mtu);
   accept_rs->app_fd = INVALID_FD;  // Ownership of the application fd has been transferred.
   new_listen_slot_id = srv_rs->id;
 
@@ -522,7 +639,8 @@
   slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_open->handle);
   memcpy(slot->addr.address, p_open->rem_bda, 6);
 
-  if (send_app_connect_signal(slot->fd, &slot->addr, slot->scn, 0, -1))
+  LOG_DEBUG(LOG_TAG, "%s  mtu = %d ", __func__,p_open->mtu);
+  if (send_app_connect_signal(slot->fd, &slot->addr, slot->scn, 0, -1, p_open->mtu))
     slot->f.connected = true;
   else
     LOG_ERROR(LOG_TAG, "%s unable to send connect completion signal to caller.", __func__);
diff --git a/btif/src/btif_sock_sdp.c b/btif/src/btif_sock_sdp.c
index a1acaff..6980c7a 100644
--- a/btif/src/btif_sock_sdp.c
+++ b/btif/src/btif_sock_sdp.c
@@ -61,7 +61,7 @@
   BTA_PBS_REALM_CHARSET,                          // realm_charset: Server only
   BTA_PBS_USERID_REQ,                             // userid_req: Server only
   (BTA_PBS_SUPF_DOWNLOAD | BTA_PBS_SURF_BROWSE),  // supported_features
-  BTA_PBS_REPOSIT_LOCAL,                          // supported_repositories
+  (BTA_PBS_REPOSIT_LOCAL  | BTA_PBS_REPOSIT_SIM), // supported_repositories
 };
 
 // object format lookup table
@@ -93,9 +93,12 @@
 
 #define RESERVED_SCN_PBS 19
 #define RESERVED_SCN_OPS 12
+#define RESERVED_SCN_FTP 20
+#define RESERVED_SCN_DUN 25
 
 #define UUID_MAX_LENGTH 16
 #define UUID_MATCHES(u1, u2) !memcmp(u1, u2, UUID_MAX_LENGTH)
+#define SPP_PROFILE_VERSION   0x0102
 
 // Adds a protocol list and service name (if provided) to an SDP record given by
 // |sdp_handle|, and marks it as browseable. This is a shortcut for defining a
@@ -349,6 +352,11 @@
   if (!SDP_AddServiceClassIdList(handle, 1, &service))
     goto error;
 
+  // Add the FTP profile descriptor.
+  stage = "profile_descriptor_list";
+  if (!SDP_AddProfileDescriptorList(handle, UUID_SERVCLASS_SERIAL_PORT,
+                                    SPP_PROFILE_VERSION))
+    goto error;
   APPL_TRACE_DEBUG("add_spp_sdp: service registered successfully, "
                    "service_name: %s, handle 0x%08x)", name, handle);
 
@@ -361,6 +369,94 @@
   return 0;
 }
 
+static int add_ftp_sdp(const char *name, const int channel)
+{
+  APPL_TRACE_DEBUG("add_ftp_sdp: channel %d, service name %s", channel, name);
+
+  int handle = SDP_CreateRecord();
+  if (handle == 0) {
+    APPL_TRACE_ERROR("add_ftp_sdp: failed to create sdp record, "
+                     "service_name: %s", name);
+    return 0;
+  }
+
+  // Create the base SDP record.
+  char *stage = "create_base_record";
+  if (!create_base_record(handle, name, channel, TRUE /* with_obex */))
+    goto error;
+
+  // Add service class.
+  stage = "service_class";
+  uint16_t service = UUID_SERVCLASS_OBEX_FILE_TRANSFER;
+  if (!SDP_AddServiceClassIdList(handle, 1, &service))
+    goto error;
+
+  // Add the FTP profile descriptor.
+  stage = "profile_descriptor_list";
+  if (!SDP_AddProfileDescriptorList(handle, UUID_SERVCLASS_OBEX_FILE_TRANSFER,
+                                    0x0101))
+    goto error;
+
+  // Notify the system that we've got a new service class UUID.
+  bta_sys_add_uuid(UUID_SERVCLASS_OBEX_FILE_TRANSFER);
+  APPL_TRACE_DEBUG("add_ftp_sdp: service registered successfully, "
+                   "service_name: %s, handle 0x%08x)", name, handle);
+
+  return handle;
+
+error:
+  SDP_DeleteRecord(handle);
+  APPL_TRACE_ERROR("add_ftp_sdp: failed to register FTP service, "
+                   "stage: %s, service_name: %s", stage, name);
+  return 0;
+
+}
+
+static int add_dun_sdp(const char *name, const int channel)
+{
+  APPL_TRACE_DEBUG("add_dun_sdp: channel %d, service name %s", channel, name);
+
+  int handle = SDP_CreateRecord();
+  if (handle == 0) {
+    APPL_TRACE_ERROR("add_dun_sdp: failed to create sdp record, "
+                     "service_name: %s", name);
+    return 0;
+  }
+
+  // Create the base SDP record.
+  char *stage = "create_base_record";
+  if (!create_base_record(handle, name, channel, FALSE /* with_obex */))
+    goto error;
+
+  // Add service class.
+  UINT16      servclass[2];
+  servclass[0] = UUID_SERVCLASS_DIALUP_NETWORKING;
+  servclass[1] = UUID_SERVCLASS_GENERIC_NETWORKING;
+  stage = "service_class";
+  if (!SDP_AddServiceClassIdList(handle, 2, servclass))
+    goto error;
+
+  // Add the DUN profile descriptor.
+  stage = "profile_descriptor_list";
+  if (!SDP_AddProfileDescriptorList(handle, UUID_SERVCLASS_DIALUP_NETWORKING,
+                                    0x0101))
+    goto error;
+
+  // Notify the system that we've got a new service class UUID.
+  bta_sys_add_uuid(UUID_SERVCLASS_DIALUP_NETWORKING);
+  APPL_TRACE_DEBUG("add_dun_sdp: service registered successfully, "
+                   "service_name: %s, handle 0x%08x)", name, handle);
+
+  return handle;
+
+error:
+  SDP_DeleteRecord(handle);
+  APPL_TRACE_ERROR("add_dun_sdp: failed to register DUN service, "
+                   "stage: %s, service_name: %s", stage, name);
+  return 0;
+
+}
+
 // Adds an RFCOMM SDP record for a service with the given |name|, |uuid|, and
 // |channel|. This function attempts to identify the type of the service based
 // upon its |uuid|, and will override the |channel| with a reserved channel
@@ -400,6 +496,10 @@
   } else if (UUID_MATCHES(UUID_MAP_MAS,uuid)) {
     // Record created by new SDP create record interface
     handle = 0xff;
+  } else if (UUID_MATCHES(UUID_FTP,uuid)) {
+    handle = add_ftp_sdp(name, final_channel);
+  } else if (UUID_MATCHES(UUID_DUN,uuid)) {
+    handle = add_dun_sdp(name, final_channel);
   } else {
     handle = add_sdp_by_uuid(name, uuid, final_channel);
   }
@@ -411,6 +511,8 @@
   switch(channel) {
     case RESERVED_SCN_PBS:
     case RESERVED_SCN_OPS:
+    case RESERVED_SCN_FTP:
+    case RESERVED_SCN_DUN:
       return TRUE;
   }
 
@@ -422,6 +524,10 @@
     return RESERVED_SCN_PBS;
   } else if (UUID_MATCHES(UUID_OBEX_OBJECT_PUSH, uuid)) {
     return RESERVED_SCN_OPS;
+  } else if (UUID_MATCHES(UUID_FTP, uuid)) {
+    return RESERVED_SCN_FTP;
+  } else if (UUID_MATCHES(UUID_DUN, uuid)) {
+    return RESERVED_SCN_DUN;
   }
 
   return -1;
@@ -441,6 +547,14 @@
         uuid = UUID_OBEX_OBJECT_PUSH;
         break;
 
+      case RESERVED_SCN_FTP:
+        uuid = UUID_FTP;
+        break;
+
+      case RESERVED_SCN_DUN:
+        uuid = UUID_DUN;
+        break;
+
       default:
         uuid = UUID_SPP;
         break;
diff --git a/btif/src/btif_sock_thread.c b/btif/src/btif_sock_thread.c
index 889c259..d1651c8 100644
--- a/btif/src/btif_sock_thread.c
+++ b/btif/src/btif_sock_thread.c
@@ -44,6 +44,7 @@
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/un.h>
+#include <sys/prctl.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -551,7 +552,7 @@
                     ps_i, MAX_POLL, count, ts[h].poll_count);
             return;
         }
-        if(ts[h].ps[ps_i].pfd.fd >= 0)
+        if(ts[h].ps[ps_i].pfd.fd >= 0 && pfd_i < MAX_POLL)
         {
             pfds[pfd_i] =  ts[h].ps[ps_i].pfd;
             ts[h].psi[pfd_i] = ps_i;
@@ -566,6 +567,8 @@
     struct pollfd pfds[MAX_POLL];
     memset(pfds, 0, sizeof(pfds));
     int h = (intptr_t)arg;
+
+    prctl(PR_SET_NAME, (unsigned long)"btif_sock_poll", 0, 0, 0);
     for(;;)
     {
         prepare_poll_fds(h, pfds);
diff --git a/btif/src/btif_stack_log.c b/btif/src/btif_stack_log.c
new file mode 100644
index 0000000..40612b3
--- /dev/null
+++ b/btif/src/btif_stack_log.c
@@ -0,0 +1,63 @@
+/*********************************************************************
+*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*   * Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   * Redistributions in binary form must reproduce the above
+*     copyright notice, this list of conditions and the following
+*     disclaimer in the documentation and/or other materials provided
+*     with the distribution.
+*   * Neither the name of The Linux Foundation nor the names of its
+*     contributors may be used to endorse or promote products derived
+*     from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <hardware/bluetooth.h>
+
+#define LOG_TAG "STACK_LOG"
+
+#include "btif_api.h"
+#include "bt_types.h"
+#include "bt_trace.h"
+#include "logging.h"
+
+
+static void setLog( const char* log_layer, UINT16 log_level);
+
+static const btstacklog_interface_t btstacklogInterface = {
+    sizeof(btstacklog_interface_t),
+    setLog,
+};
+
+const btstacklog_interface_t *btif_stack_log_interface( void )
+{
+    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
+    return &btstacklogInterface;
+}
+
+static void setLog( const char* log_layer, UINT16 log_level)
+{
+    BTA_setStackLog( log_layer, log_level);
+}
+
diff --git a/btif/src/btif_storage.c b/btif/src/btif_storage.c
index 468c6f0..d3784f9 100644
--- a/btif/src/btif_storage.c
+++ b/btif/src/btif_storage.c
@@ -167,7 +167,7 @@
 
 static bt_status_t btif_in_fetch_bonded_ble_device(const char *remote_bd_addr,int add,
                                               btif_bonded_devices_t *p_bonded_devices);
-static bt_status_t btif_in_fetch_bonded_device(const char *bdstr);
+static bt_status_t btif_in_fetch_bonded_device(const char *bdstr, int *dev_type);
 
 /************************************************************************************
 **  Static functions
@@ -176,6 +176,8 @@
 static int prop2cfg(bt_bdaddr_t *remote_bd_addr, bt_property_t *prop)
 {
     bdstr_t bdstr = {0};
+    int name_length = 0;
+    int dev_type = BT_DEVICE_TYPE_BREDR;
     if(remote_bd_addr)
         bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
     BTIF_TRACE_DEBUG("in, bd addr:%s, prop type:%d, len:%d", bdstr, prop->type, prop->len);
@@ -192,13 +194,19 @@
                                 BTIF_STORAGE_PATH_REMOTE_DEVTIME, (int)time(NULL));
             break;
         case BT_PROPERTY_BDNAME:
-            strncpy(value, (char*)prop->val, prop->len);
-            value[prop->len]='\0';
+            name_length = prop->len > BTM_MAX_LOC_BD_NAME_LEN ? BTM_MAX_LOC_BD_NAME_LEN:
+                                                                               prop->len;
+            strncpy(value, (char*)prop->val, name_length);
+            value[name_length]='\0';
             if(remote_bd_addr)
                 btif_config_set_str(bdstr,
                                 BTIF_STORAGE_PATH_REMOTE_NAME, value);
-            else btif_config_set_str("Adapter",
+            else
+            {
+                btif_config_set_str("Adapter",
                                 BTIF_STORAGE_KEY_ADAPTER_NAME, value);
+                btif_config_flush();
+            }
             break;
         case BT_PROPERTY_REMOTE_FRIENDLY_NAME:
             strncpy(value, (char*)prop->val, prop->len);
@@ -226,6 +234,7 @@
             uint32_t i;
             char buf[64];
             value[0] = 0;
+            int size = sizeof(value);
             for (i=0; i < (prop->len)/sizeof(bt_uuid_t); i++)
             {
                 bt_uuid_t *p_uuid = (bt_uuid_t*)prop->val + i;
@@ -235,9 +244,8 @@
                     android_errorWriteLog(0x534e4554, "73963551");
                     return FALSE;
                 }
-                strcat(value, buf);
-                //strcat(value, ";");
-                strcat(value, " ");
+                strlcat(value, buf, size);
+                strlcat(value, " ", size);
             }
             btif_config_set_str(bdstr, BTIF_STORAGE_PATH_REMOTE_SERVICE, value);
             break;
@@ -263,8 +271,14 @@
     }
 
     /* save changes if the device was bonded */
-    if (btif_in_fetch_bonded_device(bdstr) == BT_STATUS_SUCCESS) {
-      btif_config_save();
+    if (btif_in_fetch_bonded_device(bdstr, &dev_type) == BT_STATUS_SUCCESS) {
+      // flush is expensive, avoid for BLE devices during BLE Scanning
+      if(dev_type == BT_DEVICE_TYPE_BREDR)
+      {
+        btif_config_flush();
+      } else {
+        btif_config_save();
+      }
     }
 
     return TRUE;
@@ -394,9 +408,10 @@
 ** Returns          BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
 **
 *******************************************************************************/
-static bt_status_t btif_in_fetch_bonded_device(const char *bdstr)
+static bt_status_t btif_in_fetch_bonded_device(const char *bdstr, int *p_dev_type)
 {
     BOOLEAN bt_linkkey_file_found=FALSE;
+    BOOLEAN bt_ltk_found=FALSE;
 
         LINK_KEY link_key;
         size_t size = sizeof(link_key);
@@ -413,17 +428,23 @@
             }
         }
 #if (BLE_INCLUDED == TRUE)
-        if((btif_in_fetch_bonded_ble_device(bdstr, FALSE, NULL) != BT_STATUS_SUCCESS)
-                && (!bt_linkkey_file_found))
+        if (btif_in_fetch_bonded_ble_device(bdstr, FALSE, NULL) == BT_STATUS_SUCCESS)
+           bt_ltk_found = TRUE;
+
+        if(!bt_ltk_found && !bt_linkkey_file_found)
         {
-            BTIF_TRACE_DEBUG("Remote device:%s, no link key or ble key found", bdstr);
-            return BT_STATUS_FAIL;
+           BTIF_TRACE_DEBUG("Remote device:%s, no link key or ble key found", bdstr);
+           return BT_STATUS_FAIL;
+        } else {
+           btif_config_get_int(bdstr, "DevType", p_dev_type);
         }
 #else
         if((!bt_linkkey_file_found))
         {
             BTIF_TRACE_DEBUG("Remote device:%s, no link key found", bdstr);
             return BT_STATUS_FAIL;
+        } else {
+           btif_config_get_int(bdstr, "DevType", p_dev_type);
         }
 #endif
     return BT_STATUS_SUCCESS;
@@ -878,6 +899,27 @@
 
 /*******************************************************************************
 **
+** Function         btif_storage_is_device_bonded
+**
+** Description      BTIF storage API - checks if device present in bonded list
+**
+** Returns          TRUE if the device is bonded
+**                  FALSE otherwise
+**
+*******************************************************************************/
+BOOLEAN btif_storage_is_device_bonded(bt_bdaddr_t *remote_bd_addr)
+{
+    bdstr_t bdstr;
+    bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
+    if((btif_config_exist(bdstr, "LinkKey")) &&
+       (btif_config_exist(bdstr, "LinkKeyType")))
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/*******************************************************************************
+**
 ** Function         btif_storage_load_bonded_devices
 **
 ** Description      BTIF storage API - Loads all the bonded devices from NVRAM
@@ -1370,6 +1412,7 @@
     uint16_t attr_mask;
     uint8_t  sub_class;
     uint8_t  app_id;
+    int      dev_type;
 
     memset(&dscp_info, 0, sizeof(dscp_info));
     for (const btif_config_section_iter_t *iter = btif_config_section_begin(); iter != btif_config_section_end(); iter = btif_config_section_next(iter)) {
@@ -1379,7 +1422,7 @@
 
         BTIF_TRACE_DEBUG("Remote device:%s", name);
         int value;
-        if(btif_in_fetch_bonded_device(name) == BT_STATUS_SUCCESS)
+        if(btif_in_fetch_bonded_device(name, &dev_type) == BT_STATUS_SUCCESS)
         {
             if(btif_config_get_int(name, "HidAttrMask", &value))
             {
diff --git a/btif/src/btif_util.c b/btif/src/btif_util.c
index a8c58c9..18c9c5e 100644
--- a/btif/src/btif_util.c
+++ b/btif/src/btif_util.c
@@ -50,6 +50,7 @@
 #include "btif_dm.h"
 #include "btu.h"
 #include "bt_common.h"
+#include "btif_av.h"
 
 /************************************************************************************
 **  Constants & Macros
@@ -491,6 +492,8 @@
         CASE_RETURN_STR(BTA_AV_VENDOR_RSP_EVT)
         CASE_RETURN_STR(BTA_AV_META_MSG_EVT)
         CASE_RETURN_STR(BTA_AV_RC_FEAT_EVT)
+        CASE_RETURN_STR(BTA_AV_BROWSE_MSG_EVT)
+        CASE_RETURN_STR(BTIF_AV_CLEANUP_REQ_EVT)
         default:
             return "UNKNOWN_EVENT";
    }
@@ -509,7 +512,7 @@
         CASE_RETURN_STR(AVRC_EVT_SYSTEM_STATUS_CHANGE)
         CASE_RETURN_STR(AVRC_EVT_APP_SETTING_CHANGE)
         CASE_RETURN_STR(AVRC_EVT_VOLUME_CHANGE)
-
+        CASE_RETURN_STR(AVRC_EVT_NOW_PLAYING_CHANGE)
         default:
             return "Unhandled Event ID";
     }
@@ -536,6 +539,11 @@
         CASE_RETURN_STR(AVRC_PDU_SET_ADDRESSED_PLAYER)
         CASE_RETURN_STR(AVRC_PDU_CHANGE_PATH)
         CASE_RETURN_STR(AVRC_PDU_GET_CAPABILITIES)
+        CASE_RETURN_STR(AVRC_PDU_GET_ITEM_ATTRIBUTES)
+        CASE_RETURN_STR(AVRC_PDU_GET_FOLDER_ITEMS)
+        CASE_RETURN_STR(AVRC_PDU_SET_BROWSED_PLAYER)
+        CASE_RETURN_STR(AVRC_PDU_PLAY_ITEM)
+        CASE_RETURN_STR(AVRC_PDU_GET_TOTAL_NUMBER_OF_ITEMS)
         default:
             return "Unknown PDU";
     }
diff --git a/btif/src/btif_vendor.c b/btif/src/btif_vendor.c
new file mode 100644
index 0000000..7bc7703
--- /dev/null
+++ b/btif/src/btif_vendor.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2016 The Linux Foundation. All rights reserved
+ * Not a Contribution.
+ *  Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/************************************************************************************
+ *
+ *  Filename:      btif_vendor.c
+ *
+ *  Description:   Vendor Bluetooth Interface
+ *
+ *
+ ***********************************************************************************/
+
+#include <hardware/vendor.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define LOG_TAG "bt_btif_vendor"
+
+#include <cutils/properties.h>
+#include "bt_utils.h"
+#include "btif_common.h"
+#include "btif_util.h"
+#include "btif_profile_queue.h"
+#include "stack_config.h"
+#include "stack_manager.h"
+#include "device/include/interop_config.h"
+#include "device/include/interop.h"
+
+#define BTA_SERVICE_ID_TO_SERVICE_MASK(id)  (1 << (id))
+extern bt_status_t btif_in_execute_service_request(tBTA_SERVICE_ID service_id,
+                                               BOOLEAN b_enable);
+static void get_logger_config_value(void);
+void btif_vendor_snooplog_status_event(UINT16, char *p_param);
+
+btvendor_callbacks_t *bt_vendor_callbacks = NULL;
+
+#define BTIF_VENDOR_BREDR_CLEANUP 1
+
+/*******************************************************************************
+** VENDOR INTERFACE FUNCTIONS
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** Function         btif_vendor_init
+**
+** Description     initializes the vendor interface
+**
+** Returns         bt_status_t
+**
+*******************************************************************************/
+static bt_status_t init( btvendor_callbacks_t* callbacks)
+{
+    LOG_ERROR(LOG_TAG,"init");
+    bt_vendor_callbacks = callbacks;
+
+    get_logger_config_value();
+
+    return BT_STATUS_SUCCESS;
+}
+
+static void ssrcleanup(void)
+{
+    LOG_INFO(LOG_TAG,"ssrcleanup");
+    int soc_type = get_soc_type();
+    if (soc_type == BT_SOC_ROME || soc_type == BT_SOC_CHEROKEE)
+        btif_ssr_cleanup();
+    return;
+}
+
+static void btif_vendor_bredr_cleanup_event(UINT16 event, char *p_param)
+{
+    tBTA_SERVICE_MASK service_mask;
+    uint32_t i;
+    service_mask = btif_get_enabled_services_mask();
+    for (i = 0; i <= BTA_MAX_SERVICE_ID; i++)
+    {
+        if (i != BTA_BLE_SERVICE_ID && (service_mask &
+              (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(i))))
+        {
+            btif_in_execute_service_request(i, FALSE);
+        }
+    }
+    btif_queue_release();
+    HAL_CBACK(bt_vendor_callbacks, bredr_cleanup_cb, true);
+}
+
+static void bredrcleanup(void)
+{
+    LOG_INFO(LOG_TAG,"bredrcleanup");
+    btif_transfer_context(btif_vendor_bredr_cleanup_event,BTIF_VENDOR_BREDR_CLEANUP,
+                          NULL, 0, NULL);
+}
+
+static void capture_vnd_logs(void)
+{
+    LOG_INFO(LOG_TAG,"capture_vnd_logs");
+    GENERATE_VND_LOGS();
+}
+
+static void cleanup(void)
+{
+    LOG_INFO(LOG_TAG,"cleanup");
+    if (bt_vendor_callbacks)
+        bt_vendor_callbacks = NULL;
+}
+
+// API's to match entries with in dynamic interop database
+static bool interop_db_match(int feature, int type, void *value) {
+    if ( type == INTEROP_BL_TYPE_ADDR)
+        return interop_database_match_addr((interop_feature_t)feature, (bt_bdaddr_t *)value);
+    else if ( type == INTEROP_BL_TYPE_NAME)
+        return interop_database_match_name((interop_feature_t)feature, (char *)value);
+    return false;
+}
+
+static const btvendor_interface_t btvendorInterface = {
+    sizeof(btvendorInterface),
+    init,
+    ssrcleanup,
+    bredrcleanup,
+    capture_vnd_logs,
+    cleanup,
+    interop_db_match,
+};
+
+/*******************************************************************************
+** LOCAL FUNCTIONS
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** Function         btif_vendor_get_interface
+**
+** Description      Get the vendor callback interface
+**
+** Returns          btvendor_interface_t
+**
+*******************************************************************************/
+const btvendor_interface_t *btif_vendor_get_interface()
+{
+    BTIF_TRACE_EVENT("%s", __FUNCTION__);
+    return &btvendorInterface;
+}
+
+
+#ifdef BLUEDROID_DEBUG
+/*******************************************************************************
+**
+** Function         set_logging_pref
+**
+** Description      Set logging preference property to control BT logging
+**                  based on config file or developer option
+**
+** Returns          void
+**
+*******************************************************************************/
+void set_logging_pref(uint16_t pref_val)
+{
+  char new_log_pref[2];
+  snprintf(new_log_pref, 2, "%d", pref_val);
+  property_set("persist.bluetooth.log_pref", new_log_pref);
+  LOG_INFO(LOG_TAG, "%s, New Logging preference value: %d", __func__, pref_val);
+}
+
+/*******************************************************************************
+**
+** Function         get_logging_pref
+**
+** Description      Returns current logging preference to set logging status
+**                  based on config file or developer option
+**
+** Returns          void
+**
+*******************************************************************************/
+uint16_t get_logging_pref()
+{
+  return (uint16_t)property_get_int32("persist.bluetooth.log_pref", NO_PREFERENCE);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         get_logger_config_value
+**
+** Description      Set logging option based on flag values set
+**                  in config file
+**
+** Returns          void
+**
+*******************************************************************************/
+static void get_logger_config_value()
+{
+  bool hci_ext_dump_enabled = false;
+  bool btsnoop_conf_from_file = false;
+
+  LOG_INFO(LOG_TAG, "%s", __func__);
+
+#ifdef BLUEDROID_DEBUG
+  uint16_t logging_pref;
+  logging_pref = get_logging_pref();
+
+  LOG_INFO(LOG_TAG, "%s, logging_pref = %d", __func__, logging_pref);
+  if(logging_pref == DEV_OPT_PREFERENCE)
+    return;
+#endif
+
+  stack_config_get_interface()->get_btsnoop_ext_options(&hci_ext_dump_enabled, &btsnoop_conf_from_file);
+
+  /* ToDo: Change dependency to work on one config option*/
+#ifdef BLUEDROID_DEBUG
+  if(!btsnoop_conf_from_file)
+    hci_ext_dump_enabled = true;
+#endif
+
+  if(hci_ext_dump_enabled)
+    bt_logger_enabled = true;
+}
+
+#ifdef BLUEDROID_DEBUG
+/*******************************************************************************
+**
+** Function         enable_bt_logger_debug
+**
+** Description      enable Bluetooth Unified logger based on values
+**                  from config file and developer option and current
+**                  logging preference.
+**
+** Returns          void
+**
+*******************************************************************************/
+void enable_bt_logger_debug(bool enable)
+{
+    if(stack_manager_get_interface()->get_stack_is_running()) {
+        if(enable && !bt_logger_enabled)
+        {
+            property_set("bluetooth.startbtlogger", "true");
+            usleep(500000);
+            bt_logger_enabled = true;
+            init_vnd_Logger();
+        }
+        set_logging_pref(DEV_OPT_PREFERENCE);
+    } else {
+        uint16_t curr_log_pref;
+        curr_log_pref = get_logging_pref();
+
+        LOG_INFO(LOG_TAG, "config_hci_snoop_log, curr_log_pref = %d", curr_log_pref);
+        if(curr_log_pref < DEV_OPT_PREFERENCE && enable != bt_logger_enabled) {
+            if(curr_log_pref == bt_logger_enabled) {
+                /*It means user have updated the logging option
+                 *from Developer Option while Bluetooth was Off.*/
+                bt_logger_enabled = enable;
+                set_logging_pref(DEV_OPT_PREFERENCE);
+            } else {
+                /*It means user have updated the logging option
+                 *from bt_stack.conf file.*/
+                set_logging_pref(bt_logger_enabled);
+            }
+        } else if(curr_log_pref == DEV_OPT_PREFERENCE && enable) {
+            bt_logger_enabled = enable;
+        }
+        LOG_INFO(LOG_TAG, "config_hci_snoop_log, logging status = %d", bt_logger_enabled);
+        if(bt_logger_enabled)
+            property_set("bluetooth.startbtlogger", "true");
+    }
+}
+#else
+/*******************************************************************************
+**
+** Function         enable_bt_logger
+**
+** Description      Enable Bluetooth Unified Logger based on input
+**                  from developer option.
+**
+** Returns          void
+**
+*******************************************************************************/
+void enable_bt_logger(bool enable)
+{
+    if(stack_manager_get_interface()->get_stack_is_running()) {
+        if(enable && !bt_logger_enabled)
+        {
+            property_set("bluetooth.startbtlogger", "true");
+            usleep(500000);
+            bt_logger_enabled = true;
+            init_vnd_Logger();
+        }
+    } else {
+        bt_logger_enabled = enable;
+        if(bt_logger_enabled)
+            property_set("bluetooth.startbtlogger", "true");
+    }
+}
+#endif
+
+/*******************************************************************************
+**
+** Function        btif_vendor_snooplog_status_event
+**
+** Description     updates snoop log status to application layer
+**
+** Returns         void
+**
+*******************************************************************************/
+void btif_vendor_snooplog_status_event(UINT16 status, char *p_param)
+{
+    LOG_INFO(LOG_TAG, "%s", __func__);
+    HAL_CBACK(bt_vendor_callbacks, update_snooplog_status_cb, status);
+}
diff --git a/btif/src/stack_manager.c b/btif/src/stack_manager.c
index 288f697..f6a5298 100644
--- a/btif/src/stack_manager.c
+++ b/btif/src/stack_manager.c
@@ -21,6 +21,7 @@
 #include "stack_manager.h"
 
 #include <hardware/bluetooth.h>
+#include <cutils/properties.h>
 
 #include "btcore/include/module.h"
 #include "btcore/include/osi_module.h"
@@ -53,6 +54,13 @@
 static void event_signal_stack_up(void *context);
 static void event_signal_stack_down(void *context);
 
+extern void btif_vendor_snooplog_status_event(UINT16, char *p_param);
+extern void set_logging_pref(uint16_t pref_val);
+
+#ifdef BLUEDROID_DEBUG
+extern uint16_t get_logging_pref();
+#endif
+
 // Unvetted includes/imports, etc which should be removed or vetted in the future
 static future_t *hack_future;
 void bte_main_enable();
@@ -139,6 +147,18 @@
 
   ensure_stack_is_initialized();
 
+  init_vnd_Logger();
+#ifdef BLUEDROID_DEBUG
+  uint16_t logging_pref;
+  logging_pref = get_logging_pref();
+
+  if(logging_pref != DEV_OPT_PREFERENCE) {
+    btif_transfer_context(btif_vendor_snooplog_status_event, bt_logger_enabled,
+                NULL, 0, NULL);
+    set_logging_pref(bt_logger_enabled);
+  }
+#endif
+
   LOG_INFO(LOG_TAG, "%s is bringing up the stack", __func__);
   future_t *local_hack_future = future_new();
   hack_future = local_hack_future;
@@ -200,8 +220,6 @@
   ensure_stack_is_not_running();
 
   LOG_INFO(LOG_TAG, "%s is cleaning up the stack", __func__);
-  future_t *local_hack_future = future_new();
-  hack_future = local_hack_future;
   stack_is_initialized = false;
 
   btif_cleanup_bluetooth();
@@ -211,7 +229,8 @@
   module_management_stop();
   LOG_INFO(LOG_TAG, "%s finished", __func__);
 
-cleanup:;
+cleanup:
+  clean_vnd_logger();
   semaphore_t *semaphore = (semaphore_t *)context;
   if (semaphore)
     semaphore_post(semaphore);
diff --git a/conf/Android.mk b/conf/Android.mk
index 5bc5a63..cd723da 100644
--- a/conf/Android.mk
+++ b/conf/Android.mk
@@ -20,3 +20,15 @@
 LOCAL_SRC_FILES := $(LOCAL_MODULE)
 include $(BUILD_PREBUILT)
 
+include $(CLEAR_VARS)
+ifneq ($(TARGET_SUPPORTS_WEARABLES),true)
+LOCAL_PATH := vendor/qcom/opensource/bluetooth/system_bt_ext/conf/
+else
+LOCAL_PATH := device/qcom/msm8909w/opensource/bluetooth/system_bt_ext/conf/
+endif
+LOCAL_MODULE := interop_database.conf
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/bluetooth
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES :=  $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
diff --git a/conf/bt_did.conf b/conf/bt_did.conf
index ea89c06..5a29c73 100644
--- a/conf/bt_did.conf
+++ b/conf/bt_did.conf
@@ -7,7 +7,8 @@
 
 # Vendor ID '0xFFFF' indicates no Device ID Service Record is present in the device
 # 0x000F = Broadcom Corporation (default)
-#vendorId = 0x000F
+# 0x001D = Qualcomm
+vendorId = 0x001D
 
 # Vendor ID Source
 # 0x0001 = Bluetooth SIG assigned Device ID Vendor ID value (default)
diff --git a/conf/bt_stack.conf b/conf/bt_stack.conf
index a0afcb5..5516ac5 100644
--- a/conf/bt_stack.conf
+++ b/conf/bt_stack.conf
@@ -1,6 +1,12 @@
+# Enable BtSnoop configuration from this config file
+# Snoop is enabled by default on userdebug builds, below configuration
+# enables to override it and take effect from the configurations here.
+BtSnoopConfigFromFile=false
+
 # Enable BtSnoop logging function
 # valid value : true, false
 BtSnoopLogOutput=false
+BtSnoopExtDump=false
 
 # BtSnoop log output file
 BtSnoopFileName=/data/misc/bluetooth/logs/btsnoop_hci.log
@@ -54,6 +60,10 @@
 # SMP Pair options (formatted as hex bytes) auth, io, ikey, rkey, ksize
 #PTS_SmpOptions=0xD,0x4,0xf,0xf,0x10
 
+# Enable LE  non-conn adv mode
+# valid value: true, false
+#PTS_EnableNonConnAdvMode=true
+
 # SMP Certification Failure Cases
 # Fail case number range from 1 to 9 will set up remote device for test
 # case execution. Setting PTS_SmpFailureCase to 0 means normal operation.
@@ -68,4 +78,3 @@
 #  8 = SMP_PASSKEY_ENTRY_FAIL
 #  9 = SMP_NUMERIC_COMPAR_FAIL;
 #PTS_SmpFailureCase=0
-
diff --git a/conf/iot_devlist.conf b/conf/iot_devlist.conf
new file mode 100755
index 0000000..db09b90
--- /dev/null
+++ b/conf/iot_devlist.conf
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *        * Redistributions of source code must retain the above copyright
+ *          notice, this list of conditions and the following disclaimer.
+ *        * Redistributions in binary form must reproduce the above copyright
+ *            notice, this list of conditions and the following disclaimer in the
+ *            documentation and/or other materials provided with the distribution.
+ *        * Neither the name of The Linux Foundation nor
+ *            the names of its contributors may be used to endorse or promote
+ *            products derived from this software without specific prior written
+ *            permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.    IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+# Place holder for all IOT devices to be blacklisted
+# Blacklist mechanism will detect the device in runtime based on issue condition
+# and black list the device
diff --git a/device/Android.mk b/device/Android.mk
index c5b9377..bb9a061 100644
--- a/device/Android.mk
+++ b/device/Android.mk
@@ -31,10 +31,25 @@
     $(LOCAL_PATH)/../stack/include \
     $(bluetooth_C_INCLUDES)
 
+ifneq ($(TARGET_SUPPORTS_WEARABLES),true)
+LOCAL_C_INCLUDES += \
+    vendor/qcom/opensource/bluetooth/system_bt_ext
+else
+LOCAL_C_INCLUDES += \
+    device/qcom/msm8909w/opensource/bluetooth/system_bt_ext
+endif
+
 LOCAL_SRC_FILES := \
     src/classic/peer.c \
-    src/controller.c \
-    src/interop.c
+    src/controller.c
+
+ifneq ($(TARGET_SUPPORTS_WEARABLES),true)
+LOCAL_SRC_FILES += \
+    ../../../vendor/qcom/opensource/bluetooth/system_bt_ext/device/src/interop.c
+else
+LOCAL_SRC_FILES += \
+    ../../../device/qcom/msm8909w/opensource/bluetooth/system_bt_ext/device/src/interop.c
+endif
 
 LOCAL_MODULE := libbtdevice
 LOCAL_MODULE_TAGS := optional
diff --git a/device/include/controller.h b/device/include/controller.h
index 291c33d..159cd79 100644
--- a/device/include/controller.h
+++ b/device/include/controller.h
@@ -29,6 +29,10 @@
 
 static const char CONTROLLER_MODULE[] = "controller_module";
 
+typedef struct controller_static_t {
+  void (*enable_soc_logging) (bool value);
+} controller_static_t;
+
 typedef struct controller_t {
   bool (*get_is_ready)(void);
 
@@ -49,11 +53,14 @@
   bool (*supports_rssi_with_inquiry_results)(void);
   bool (*supports_extended_inquiry_response)(void);
   bool (*supports_master_slave_role_switch)(void);
+  bool (*supports_set_le_privacy_mode)(void);
 
   bool (*supports_ble)(void);
   bool (*supports_ble_packet_extension)(void);
   bool (*supports_ble_connection_parameters_request)(void);
   bool (*supports_ble_privacy)(void);
+  bool (*supports_ble_two_mbps_rate)(void);
+  bool (*supports_ble_extended_advertisements)(void);
 
   // Get the cached acl data sizes for the controller.
   uint16_t (*get_acl_data_size_classic)(void);
@@ -76,8 +83,14 @@
   uint8_t (*get_ble_resolving_list_max_size)(void);
   void (*set_ble_resolving_list_max_size)(int resolving_list_max_size);
   uint8_t *(*get_local_supported_codecs)(uint8_t *number_of_codecs);
+  bool (*supports_ble_offload_features)(void);
+
+  uint8_t (*get_ble_adv_ext_size)(void);
+  void (*set_ble_adv_ext_size)(int adv_ext_size);
 } controller_t;
 
+const controller_static_t *controller_get_static_interface();
+
 const controller_t *controller_get_interface();
 
 const controller_t *controller_get_test_interface(
diff --git a/device/include/interop.h b/device/include/interop.h
index 05778a8..8edcd01 100644
--- a/device/include/interop.h
+++ b/device/include/interop.h
@@ -25,13 +25,15 @@
 static const char INTEROP_MODULE[] = "interop_module";
 
 // NOTE:
-// Only add values at the end of this enum and do NOT delete values
-// as they may be used in dynamic device configuration.
+// Only add values at the end of this enum and before END_OF_INTEROP_LIST
+// do NOT delete values as they may be used in dynamic device configuration.
 typedef enum {
+
+  BEGINING_OF_INTEROP_LIST = 0,
   // Disable secure connections
   // This is for pre BT 4.1/2 devices that do not handle secure mode
   // very well.
-  INTEROP_DISABLE_LE_SECURE_CONNECTIONS = 0,
+  INTEROP_DISABLE_LE_SECURE_CONNECTIONS = BEGINING_OF_INTEROP_LIST,
 
   // Some devices have proven problematic during the pairing process, often
   // requiring multiple retries to complete pairing. To avoid degrading the user
@@ -63,7 +65,114 @@
   // re-transmissions after switching to 2DH packets.
   //
   // Disable 3Mbps packets and use only 2Mbps packets for ACL links when streaming audio.
-  INTEROP_2MBPS_LINK_ONLY
+  INTEROP_2MBPS_LINK_ONLY,
+
+  // Some HID devices have proven problematic behaviour if SDP is initiated again
+  // while HID connection is in progress or if more than 1 SDP connection is created
+  // with those HID devices rsulting in issues of connection failure with such devices.
+  // To avoid degrading the user experience with those devices, SDP is not attempted
+  // as part of pairing process.
+  INTEROP_DISABLE_SDP_AFTER_PAIRING,
+
+  // Some HID pointing devices have proven problematic behaviour if pairing is initiated with
+  // them, resulting in no response for authentication request and ultimately resulting
+  // in connection failure.
+  // To avoid degrading the user experience with those devices, authentication request
+  // is not requested explictly.
+  INTEROP_DISABLE_AUTH_FOR_HID_POINTING,
+
+  // HID Keyboards that claim support for multitouch functionality have issue with
+  // normal functioning of keyboard because of issues in USB HID kernel driver.
+  // To avoid degrading the user experience with those devices, digitizer record
+  // is removed from the report descriptor.
+  INTEROP_REMOVE_HID_DIG_DESCRIPTOR,
+
+  // Some HID devices have problematic behaviour where when hid link is in Sniff
+  // and DUT is in Slave role for SCO link ( not eSCO) any solution cannot maintain
+  // the link as  SCO scheduling over a short period will overlap with Sniff link due to
+  // slave drift.
+  // To avoid degrading the user experience with those devices, sniff is disabled from
+  // link policy when sco is active, and enabled when sco is disabled.
+  INTEROP_DISABLE_SNIFF_DURING_SCO,
+
+  //Few carkits take long time to start sending AT commands
+  //Increase AG_CONN TIMEOUT so that AG connection go through
+  INTEROP_INCREASE_AG_CONN_TIMEOUT,
+
+  // Some HOGP devices do not respond well when we switch from default LE conn parameters
+  // to preferred conn params immediately post connection. Disable automatic switching to
+  // preferred conn params for such devices and allow them to explicity ask for it.
+  INTEROP_DISABLE_LE_CONN_PREFERRED_PARAMS,
+
+  //Few carkit hfp version is hfp1.5 but it support hfp indicator, violate spec
+  //remove hfp indicator for such device
+  INTEROP_DISABLE_HF_INDICATOR,
+
+  // Few remote devices do not understand AVRCP version greater than 1.3. For these
+  // devices, we would like to blacklist them and advertise AVRCP version as 1.3
+  INTEROP_ADV_AVRCP_VER_1_3,
+
+  // certain remote A2DP sinks have issue playing back Music in AAC format.
+  // disable AAC for those headsets so that it switch to SBC
+  INTEROP_DISABLE_AAC_CODEC,
+
+  // Enable AAC only for whitelist of devices
+  INTEROP_ENABLE_AAC_CODEC,
+
+  // Some car kits notifies role switch supported but it rejects
+  // the role switch and after some attempts of role switch
+  // car kits will go to bad state.
+  INTEROP_DYNAMIC_ROLE_SWITCH,
+
+  // Disable role switch for headsets/car-kits
+  // Some car kits allow role switch but when DUT initiates role switch
+  // Remote will go to bad state and its leads to LMP time out.
+  INTEROP_DISABLE_ROLE_SWITCH,
+
+  // Disable role switch for headsets/car-kits
+  // Some car kits initiate a role switch but won't initiate encryption
+  // after role switch complete
+  INTEROP_DISABLE_ROLE_SWITCH_POLICY,
+
+  INTEROP_HFP_1_7_BLACKLIST,
+
+  // Some Carkits are not initiating AVRCP Browse Channel on
+  // seeing DUT's AVRCP version as v1.6. Hence fallback DUT's
+  // AVRCP version to v1.4 for those Carkits
+  INTEROP_STORE_REMOTE_AVRCP_VERSION_1_4,
+
+  // Devices requiring this workaround do not handle Bluetooth PBAP 1.2 version correctly,
+  // leading them to go in bad state. So for better interoperability respond with PBAP 1.1
+  // as supported version.
+  INTEROP_ADV_PBAP_VER_1_1,
+
+  // Devices requiring this workaround do not handle SSR max latency values as mentioned,
+  // in their SDP HID Record properly and lead to connection timeout or lags. To prevent
+  // such scenarios, device requiring this workaorund need to use specific ssr max latency
+  // values.
+  INTEROP_UPDATE_HID_SSR_MAX_LAT,
+  // Some Carkits being AVRCP v1.3 upon receiving Play Application Setting Command Response
+  // and notification, doesn't send Passthrough commands back to DUT in Streaming State
+  INTEROP_DISABLE_PLAYER_APPLICATION_SETTING_CMDS,
+
+  // Some remotes are very strict in receiving the call active
+  // indicator and SCO connection request order for MT call.
+  // If CIEV1,1 and SCO connection request are sent back to back
+  // to SOC, it may send SCO connection request first then CIEV1,1
+  // which may lead to remotes not rendering SCO audio.
+  INTEROP_DELAY_SCO_FOR_MT_CALL,
+  // Some remotes are taking too long to respond for codec negotiation.
+  // Disable codec negotiation for such remotes and directly initiate
+  // SCO Connection.
+  INTEROP_DISABLE_CODEC_NEGOTIATION,
+
+  // Some remotes are going into sniff mode during SCO connection process and taking time
+  // for SCO connection to complete. For such devices, disable sniff when SCO is
+  // connecting and enable it after SCO disconnection.
+  INTEROP_DISABLE_SNIFF_POLICY_DURING_SCO,
+
+  END_OF_INTEROP_LIST
+
 } interop_feature_t;
 
 // Check if a given |addr| matches a known interoperability workaround as identified
@@ -80,6 +189,34 @@
 // |name| cannot be null and must be null terminated.
 bool interop_match_name(const interop_feature_t feature, const char *name);
 
+// Check if a given remote device |name| matches a known interoperability workaround.
+// Name comparisons are case sensitive and do not allow for partial matches. As in, if
+// |name| is "TEST" and a workaround exists for "TESTING", then this function will
+// return false. But, if |name| is "TESTING" and a workaround exists for "TEST", this
+// function will return true.
+// |name| cannot be null and must be null terminated.
+bool interop_match_name(const interop_feature_t feature, const char *name);
+
+// Check if a given |manufacturer| matches a known interoperability workaround as identified
+// by the |interop_feature_t| enum. This API is used for manufacturer based lookups
+// where more information is not available.
+bool interop_match_manufacturer(const interop_feature_t feature, uint16_t manufacturer);
+
+
+// Check if a given |vendor_id, product_id, name| matches a known interoperability workaround
+// as identified by the |interop_feature_t| enum. This API is used for simple name based lookups
+// where more information is not available.
+bool interop_match_vendor_product_ids(const interop_feature_t feature,
+        uint16_t vendor_id, uint16_t product_id);
+
+// Check if a given |addr| matches a known interoperability workaround as identified
+// by the |interop_feature_t| enum. This API is used for simple address based lookups
+// where more information is not available. No look-ups or random address resolution
+// are performed on |addr|. If address is matched, max latency for SSR stored for particular
+// remote device is returned.
+bool interop_match_addr_get_max_lat(const interop_feature_t feature,
+        const bt_bdaddr_t *addr, uint16_t *max_lat);
+
 // Add a dynamic interop database entry for a device matching the first |length| bytes
 // of |addr|, implementing the workaround identified by |feature|. |addr| may not be
 // null and |length| must be greater than 0 and less than sizeof(bt_bdaddr_t).
diff --git a/device/include/interop_database.h b/device/include/interop_database.h
index 49cb8a5..4423aea 100644
--- a/device/include/interop_database.h
+++ b/device/include/interop_database.h
@@ -90,10 +90,60 @@
 
   // Unknown keyboard (carried over from auto_pair_devlist.conf)
   {{{0x00, 0x0F, 0xF6,      0,0,0}}, 3, INTEROP_KEYBOARD_REQUIRES_FIXED_PIN},
+
+  // Apple Magic Mouse
+  {{{0x04, 0x0C, 0xCE,       0,0,0}}, 3, INTEROP_DISABLE_SDP_AFTER_PAIRING},
+  // Bluetooth Laser Travel Mouse
+  {{{0x00, 0x07, 0x61,       0,0,0}}, 3, INTEROP_DISABLE_SDP_AFTER_PAIRING},
+  // Microsoft Bluetooth Notebook Mouse 5000
+  {{{0x00, 0x1d, 0xd8,       0,0,0}}, 3, INTEROP_DISABLE_SDP_AFTER_PAIRING},
+  // Logitech MX Revolution Mouse
+  {{{0x00, 0x1f, 0x20,       0,0,0}}, 3, INTEROP_DISABLE_SDP_AFTER_PAIRING},
+  // Rapoo 6080 mouse
+  {{{0x6c, 0x5d, 0x63,       0,0,0}}, 3, INTEROP_DISABLE_SDP_AFTER_PAIRING},
+  // Microsoft Sculpt Touch Mouse
+  {{{0x28, 0x18, 0x78,       0,0,0}}, 3, INTEROP_DISABLE_SDP_AFTER_PAIRING},
+  // Tero's Game Controller
+  {{{0x60, 0x45, 0xBD,       0,0,0}}, 3, INTEROP_DISABLE_SDP_AFTER_PAIRING},
+
+  // Targus BT Laser Notebook Mouse
+  {{{0x00, 0x12, 0xA1,       0,0,0}}, 3, INTEROP_DISABLE_AUTH_FOR_HID_POINTING},
+
+  // Bluetooth Keyboard
+  {{{0x20, 0x4C, 0x10,       0,0,0}}, 3, INTEROP_DISABLE_SNIFF_DURING_SCO},
+
+  // Fiat Carkit
+  {{{0x00, 0x14, 0x09,       0,0,0}}, 3, INTEROP_INCREASE_AG_CONN_TIMEOUT},
+
+  // Dialog Keyboard and mouse
+  {{{0x80, 0xea, 0xca,      0,0,0}}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS},
+
+  // Marvel CK used in Mercedes C300/BMW 640i
+  // For a more specific black listing(e.g. just for Mercedes), both BD addr
+  // and device name has to be added for AVRCP 1.3 blacklisting
+  {{{0xa0, 0x56, 0xb2,      0,0,0}}, 3, INTEROP_ADV_AVRCP_VER_1_3},
+
+  // Mazda Atenza
+  {{{0x04, 0xf8, 0xc2,      0,0,0}}, 3, INTEROP_DISABLE_ABSOLUTE_VOLUME},
+  // Remote not playing back Audio, suspected to be Audio encoder version diff
+  // Beats Solo 3
+  {{{0x20, 0x3c, 0xae,      0,0,0}}, 3, INTEROP_DISABLE_AAC_CODEC},
+  //Apple Airpods Headset
+  {{{0x4c, 0x32, 0x75,      0,0,0}}, 3, INTEROP_DISABLE_AAC_CODEC},
+  // Remote sending 128 as bitrate in place of 128000
+  // Cadillac
+  {{{0x28, 0xA1, 0x83,      0,0,0}}, 3, INTEROP_DISABLE_AAC_CODEC},
+  // Buick Verona
+  {{{0xAC, 0x7A, 0x4D,      0,0,0}}, 3, INTEROP_DISABLE_AAC_CODEC},
+  //Maruthi Brezzai
+  {{{0x28, 0xa1, 0x83,      0,0,0}}, 3, INTEROP_DISABLE_AAC_CODEC},
+  // Parrot Zik2.0
+  {{{0xA0, 0x14, 0x3D,      0,0,0}}, 3, INTEROP_DISABLE_AAC_CODEC},
+
 };
 
 typedef struct {
-  char name[20];
+  char name[249];
   size_t length;
   interop_feature_t feature;
 } interop_name_entry_t;
@@ -110,5 +160,49 @@
 
   // Subaru car kits ("CAR M_MEDIA")
   {"CAR",     3, INTEROP_DISABLE_AUTO_PAIRING},
+
+  // HID SDP Blacklist
+  {"Apple Magic Mouse", 17, INTEROP_DISABLE_SDP_AFTER_PAIRING},
+  {"Bluetooth Laser Travel Mouse", 28, INTEROP_DISABLE_SDP_AFTER_PAIRING},
+  {"Microsoft Bluetooth Notebook Mouse 5000", 39, INTEROP_DISABLE_SDP_AFTER_PAIRING},
+  {"Logitech MX Revolution Mouse", 28, INTEROP_DISABLE_SDP_AFTER_PAIRING},
+  {"Microsoft Sculpt Touch Mouse", 28, INTEROP_DISABLE_SDP_AFTER_PAIRING},
+  {"Tero's Game Controller", 22, INTEROP_DISABLE_SDP_AFTER_PAIRING},
+
+  // HID Authentication Blacklist
+  {"Targus BT Laser Notebook Mouse", 30, INTEROP_DISABLE_AUTH_FOR_HID_POINTING},
+
+  //Below devices reject connection updated with preferred
+  {"BSMBB09DS", 9, INTEROP_DISABLE_LE_CONN_PREFERRED_PARAMS},
+  {"ELECOM", 6, INTEROP_DISABLE_LE_CONN_PREFERRED_PARAMS},
+  {"MB Bluetooth", 12, INTEROP_ADV_AVRCP_VER_1_3},
+
+  // HID Moto KZ500 Keyboard - Problematic SDP digitizer descriptor
+  {"Motorola Keyboard KZ500", 23, INTEROP_REMOVE_HID_DIG_DESCRIPTOR},
+  {"Motorola Keyboard KZ500 v122", 28, INTEROP_REMOVE_HID_DIG_DESCRIPTOR},
+
 };
 
+typedef struct {
+  uint16_t manufacturer;
+  interop_feature_t feature;
+} interop_manufacturer_t;
+
+static const interop_manufacturer_t interop_manufacturer_database[] = {
+  // Apple Devices
+  {76, INTEROP_DISABLE_SDP_AFTER_PAIRING},
+
+  // Apple Devices
+  {76, INTEROP_DISABLE_SNIFF_DURING_SCO},
+};
+
+typedef struct {
+  uint16_t vendor_id;
+  uint16_t product_id;
+  interop_feature_t feature;
+} interop_hid_multitouch_t;
+
+static const interop_hid_multitouch_t interop_hid_multitouch_database[] = {
+  // HID Moto KZ500 Keyboard - Problematic SDP digitizer descriptor
+  {0x22b8, 0x093d, INTEROP_REMOVE_HID_DIG_DESCRIPTOR},
+};
diff --git a/device/src/controller.c b/device/src/controller.c
index 23799d8..bb53eb3 100644
--- a/device/src/controller.c
+++ b/device/src/controller.c
@@ -21,6 +21,8 @@
 #include "device/include/controller.h"
 
 #include <assert.h>
+#include <string.h>
+#include <cutils/properties.h>
 
 #include "bt_types.h"
 #include "btcore/include/event_mask.h"
@@ -29,8 +31,11 @@
 #include "hcimsgs.h"
 #include "osi/include/future.h"
 #include "stack/include/btm_ble_api.h"
+#include "osi/include/log.h"
+#include "utils/include/bt_utils.h"
 
-const bt_event_mask_t BLE_EVENT_MASK = { "\x00\x00\x00\x00\x00\x00\x06\x7f" };
+const bt_event_mask_t BLE_EVENT_MASK = { "\x00\x00\x00\x00\x00\x0b\xfe\x7f" };
+const bt_event_mask_t BLE_EVENT_MASK_ALE_DISABLED = { "\x00\x00\x00\x00\x00\x08\x0e\x7f" };
 
 #if (BLE_INCLUDED)
 const bt_event_mask_t CLASSIC_EVENT_MASK = { HCI_DUMO_EVENT_MASK_EXT };
@@ -46,6 +51,9 @@
 #define BLE_SUPPORTED_STATES_SIZE         8
 #define BLE_SUPPORTED_FEATURES_SIZE       8
 #define MAX_LOCAL_SUPPORTED_CODECS_SIZE   8
+#define UNUSED(x) (void)(x)
+
+static bool soc_logging_enabled_via_api;
 
 static const hci_t *hci;
 static const hci_packet_factory_t *packet_factory;
@@ -70,18 +78,44 @@
 static uint16_t ble_suggested_default_data_length;
 static uint8_t local_supported_codecs[MAX_LOCAL_SUPPORTED_CODECS_SIZE];
 static uint8_t number_of_local_supported_codecs = 0;
+static uint8_t ble_adv_ext_size;
 
 static bool readable;
 static bool ble_supported;
+static bool ble_offload_features_supported;
 static bool simple_pairing_supported;
 static bool secure_connections_supported;
 
+static bool adv_ext_enabled = false;
+
 #define AWAIT_COMMAND(command) future_await(hci->transmit_command_futured(command))
 
 // Module lifecycle functions
 
+void send_soc_log_command(bool value) {
+  int soc_type = get_soc_type();
+  UINT8 param[5] = {0x10, 0x03, 0x00, 0x00, 0x01};
+  UINT8 param_cherokee[2] = {0x14, 0x01};
+  if (!value) {
+    // Disable SoC logging
+    param[1] = 0x02;
+    param_cherokee[1] = 0x00;
+  }
+
+  if (soc_type == BT_SOC_SMD) {
+    LOG_INFO(LOG_TAG, "%s for BT_SOC_SMD.", __func__);
+    BTM_VendorSpecificCommand(HCI_VS_HOST_LOG_OPCODE, 5, param, NULL);
+  } else if (soc_type == BT_SOC_CHEROKEE) {
+    LOG_INFO(LOG_TAG, "%s for BT_SOC_CHEROKEE.", __func__);
+    BTM_VendorSpecificCommand(HCI_VS_HOST_LOG_OPCODE, 2, param_cherokee, NULL);
+  }
+
+}
+
 static future_t *start_up(void) {
   BT_HDR *response;
+  int ret =0;
+  char value[PROPERTY_VALUE_MAX] = {'\0'};
 
   // Send the initial reset command
   response = AWAIT_COMMAND(packet_factory->make_reset());
@@ -105,6 +139,16 @@
 
   packet_parser->parse_generic_command_complete(response);
 
+  #ifdef QLOGKIT_USERDEBUG
+    send_soc_log_command(true);
+  #else
+    if (soc_logging_enabled_via_api) {
+      LOG_INFO(LOG_TAG, "%s for non-userdebug api = %d", __func__,
+                                           soc_logging_enabled_via_api);
+      send_soc_log_command(true);
+    }
+  #endif
+
   // Read the local version info off the controller next, including
   // information such as manufacturer and supported HCI version
   response = AWAIT_COMMAND(packet_factory->make_read_local_version_info());
@@ -177,15 +221,30 @@
     page_number++;
   }
 
+  // read BLE offload features support from controller
+  response = AWAIT_COMMAND(packet_factory->make_ble_read_offload_features_support());
+  packet_parser->parse_ble_read_offload_features_response(response, &ble_offload_features_supported);
+
 #if (SC_MODE_INCLUDED == TRUE)
-  secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(features_classic[2].as_array);
-  if (secure_connections_supported) {
-    response = AWAIT_COMMAND(packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED));
-    packet_parser->parse_generic_command_complete(response);
+  if(ble_offload_features_supported) {
+    secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(features_classic[2].as_array);
+    if (secure_connections_supported) {
+      response = AWAIT_COMMAND(packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED));
+      packet_parser->parse_generic_command_complete(response);
+    }
   }
 #endif
 
 #if (BLE_INCLUDED == TRUE)
+
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+  ret = property_get("ble.ae_supported", value, NULL);
+  if (ret) {
+    adv_ext_enabled = (strcmp(value, "true") ==0) ? true : false;
+    LOG_INFO(LOG_TAG, "%s BLE Adv Extensions enabled:%d", __func__, adv_ext_enabled);
+  }
+#endif
+
   ble_supported = last_features_classic_page_index >= 1 && HCI_LE_HOST_SUPPORTED(features_classic[1].as_array);
   if (ble_supported) {
     // Request the ble white list size next
@@ -233,8 +292,19 @@
             &ble_suggested_default_data_length);
     }
 
+    if (adv_ext_enabled && HCI_LE_ADV_EXTENSION_SUPPORTED(features_ble.as_array)) {
+        response = AWAIT_COMMAND(packet_factory->make_ble_read_adv_ext_size());
+        packet_parser->parse_ble_read_adv_ext_size_response(
+            response,
+            &ble_adv_ext_size);
+    }
+
     // Set the ble event mask next
-    response = AWAIT_COMMAND(packet_factory->make_ble_set_event_mask(&BLE_EVENT_MASK));
+    if (adv_ext_enabled) {
+        response = AWAIT_COMMAND(packet_factory->make_ble_set_event_mask(&BLE_EVENT_MASK));
+    } else {
+        response = AWAIT_COMMAND(packet_factory->make_ble_set_event_mask(&BLE_EVENT_MASK_ALE_DISABLED));
+    }
     packet_parser->parse_generic_command_complete(response);
   }
 #endif
@@ -277,6 +347,16 @@
 
 // Interface functions
 
+static void enable_soc_logging(bool value) {
+  UNUSED(soc_logging_enabled_via_api);
+#ifndef QLOGKIT_USERDEBUG
+  soc_logging_enabled_via_api = value;
+
+  if (readable)
+    send_soc_log_command(value);
+#endif
+}
+
 static bool get_is_ready(void) {
   return readable;
 }
@@ -344,6 +424,11 @@
   return HCI_READ_REMOTE_EXT_FEATURES_SUPPORTED(supported_commands);
 }
 
+static bool supports_set_le_privacy_mode(void) {
+  assert(readable);
+  return (HCI_LE_SET_PRIVACY_MODE_SUPPORTED(supported_commands));
+}
+
 static bool supports_interlaced_inquiry_scan(void) {
   assert(readable);
   return HCI_LMP_INTERLACED_INQ_SCAN_SUPPORTED(features_classic[0].as_array);
@@ -375,6 +460,15 @@
   return HCI_LE_ENHANCED_PRIVACY_SUPPORTED(features_ble.as_array);
 }
 
+static bool supports_ble_extended_advertisements(void) {
+  assert(readable);
+  assert(ble_supported);
+  if(adv_ext_enabled)
+    return HCI_LE_ADV_EXTENSION_SUPPORTED(features_ble.as_array);
+  else
+    return false;
+}
+
 static bool supports_ble_packet_extension(void) {
   assert(readable);
   assert(ble_supported);
@@ -387,6 +481,18 @@
   return HCI_LE_CONN_PARAM_REQ_SUPPORTED(features_ble.as_array);
 }
 
+static bool supports_ble_offload_features(void) {
+  assert(readable);
+  assert(ble_supported);
+  return ble_offload_features_supported;
+}
+
+static bool supports_ble_two_mbps_rate(void) {
+    assert(readable);
+    assert(ble_supported);
+    return HCI_LE_TWO_MBPS_SUPPORTED(features_ble.as_array);
+}
+
 static uint16_t get_acl_data_size_classic(void) {
   assert(readable);
   return acl_data_size_classic;
@@ -447,6 +553,22 @@
   ble_resolving_list_max_size = resolving_list_max_size;
 }
 
+static const controller_static_t static_interface = {
+  enable_soc_logging
+};
+
+static uint8_t get_ble_adv_ext_size(void) {
+    assert(readable);
+    assert(ble_supported);
+    return ble_adv_ext_size;
+}
+
+static void set_ble_adv_ext_size(int adv_sets) {
+    assert(readable);
+    assert(ble_supported);
+    ble_adv_ext_size = adv_sets;
+}
+
 static const controller_t interface = {
   get_is_ready,
 
@@ -467,11 +589,14 @@
   supports_rssi_with_inquiry_results,
   supports_extended_inquiry_response,
   supports_master_slave_role_switch,
+  supports_set_le_privacy_mode,
 
   supports_ble,
   supports_ble_packet_extension,
   supports_ble_connection_parameters_request,
   supports_ble_privacy,
+  supports_ble_two_mbps_rate,
+  supports_ble_extended_advertisements,
 
   get_acl_data_size_classic,
   get_acl_data_size_ble,
@@ -487,9 +612,17 @@
 
   get_ble_resolving_list_max_size,
   set_ble_resolving_list_max_size,
-  get_local_supported_codecs
+  get_local_supported_codecs,
+  supports_ble_offload_features,
+
+  get_ble_adv_ext_size,
+  set_ble_adv_ext_size
 };
 
+const controller_static_t *controller_get_static_interface() {
+  return &static_interface;
+}
+
 const controller_t *controller_get_interface() {
   static bool loaded = false;
   if (!loaded) {
diff --git a/device/src/interop.c b/device/src/interop.c
index 50020f7..33f963f 100644
--- a/device/src/interop.c
+++ b/device/src/interop.c
@@ -62,6 +62,40 @@
     if (feature == interop_name_database[i].feature &&
         strlen(name) >= interop_name_database[i].length &&
         strncmp(name, interop_name_database[i].name, interop_name_database[i].length) == 0) {
+      LOG_WARN(LOG_TAG, "%s() Device with name: %s is a match for interop workaround %s", __func__,
+          name, interop_feature_string_(feature));
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool interop_match_manufacturer(const interop_feature_t feature, uint16_t manufacturer) {
+  const size_t db_size = sizeof(interop_manufacturer_database) / sizeof(interop_manufacturer_t);
+
+  for (size_t i = 0; i != db_size; ++i) {
+    if (feature == interop_manufacturer_database[i].feature &&
+        manufacturer == interop_manufacturer_database[i].manufacturer) {
+      LOG_WARN(LOG_TAG, "%s() Device with manufacturer id: %d is a match for interop "
+        "workaround %s", __func__, manufacturer, interop_feature_string_(feature));
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool interop_match_vendor_product_ids(const interop_feature_t feature,
+        uint16_t vendor_id, uint16_t product_id) {
+  const size_t db_size = sizeof(interop_hid_multitouch_database) / sizeof(interop_hid_multitouch_t);
+
+  for (size_t i = 0; i != db_size; ++i) {
+    if (vendor_id == interop_hid_multitouch_database[i].vendor_id &&
+        product_id == interop_hid_multitouch_database[i].product_id) {
+      LOG_WARN(LOG_TAG, "%s() Device with vendor_id: %d product_id: %d is a match for "
+          "interop workaround %s", __func__, vendor_id, product_id,
+          interop_feature_string_(feature));
       return true;
     }
   }
@@ -115,6 +149,14 @@
     CASE_RETURN_STR(INTEROP_DISABLE_AUTO_PAIRING)
     CASE_RETURN_STR(INTEROP_KEYBOARD_REQUIRES_FIXED_PIN)
     CASE_RETURN_STR(INTEROP_2MBPS_LINK_ONLY)
+    CASE_RETURN_STR(INTEROP_DISABLE_SDP_AFTER_PAIRING)
+    CASE_RETURN_STR(INTEROP_DISABLE_AUTH_FOR_HID_POINTING)
+    CASE_RETURN_STR(INTEROP_REMOVE_HID_DIG_DESCRIPTOR)
+    CASE_RETURN_STR(INTEROP_DISABLE_SNIFF_DURING_SCO)
+    CASE_RETURN_STR(INTEROP_INCREASE_AG_CONN_TIMEOUT)
+    CASE_RETURN_STR(INTEROP_DISABLE_LE_CONN_PREFERRED_PARAMS)
+    CASE_RETURN_STR(INTEROP_ADV_AVRCP_VER_1_3)
+    CASE_RETURN_STR(INTEROP_DISABLE_AAC_CODEC)
   }
 
   return "UNKNOWN";
diff --git a/embdrv/sbc/encoder/include/sbc_encoder.h b/embdrv/sbc/encoder/include/sbc_encoder.h
index a1c963f..977473d 100644
--- a/embdrv/sbc/encoder/include/sbc_encoder.h
+++ b/embdrv/sbc/encoder/include/sbc_encoder.h
@@ -175,6 +175,7 @@
     SINT16 *ps16PcmBuffer;
 #else
     SINT16 as16PcmBuffer[SBC_MAX_NUM_FRAME*SBC_MAX_NUM_OF_BLOCKS * SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS];
+    SINT32 as32PcmBuffer[SBC_MAX_NUM_FRAME*SBC_MAX_NUM_OF_BLOCKS * SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS];
 #endif
 
     SINT16  s16ScartchMemForBitAlloc[16];
diff --git a/hci/Android.mk b/hci/Android.mk
index 0727100..ddb533d 100644
--- a/hci/Android.mk
+++ b/hci/Android.mk
@@ -34,9 +34,14 @@
 
 LOCAL_MODULE := libbt-hci
 
-ifeq ($(BLUETOOTH_HCI_USE_MCT),true)
-LOCAL_CFLAGS += -DHCI_USE_MCT
+ifeq ($(TARGET_BUILD_VARIANT),userdebug)
+    LOCAL_CFLAGS += -DBTSNOOP_DEFAULT=TRUE
 endif
+
+ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
+LOCAL_CFLAGS += -DENABLE_DBG_FLAGS
+endif
+
 LOCAL_CFLAGS += $(bluetooth_CFLAGS)
 LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS)
 LOCAL_CPPFLAGS += $(bluetooth_CPPFLAGS)
diff --git a/hci/include/bt_vendor_lib.h b/hci/include/bt_vendor_lib.h
index b4396ea..82c46b6 100644
--- a/hci/include/bt_vendor_lib.h
+++ b/hci/include/bt_vendor_lib.h
@@ -196,6 +196,12 @@
  */
     BT_VND_OP_A2DP_OFFLOAD_STOP,
 
+    FM_VND_OP_POWER_CTRL,
+
+    BT_VND_OP_FM_USERIAL_OPEN,
+
+    BT_VND_OP_FM_USERIAL_CLOSE,
+
 } bt_vendor_opcode_t;
 
 /** Power on/off control states */
@@ -391,6 +397,11 @@
 
     /** Closes the interface */
     void  (*cleanup)(void);
+
+    /** SSR cleanup is used in HW reset cases
+     * which would close all the client channels
+     * and turns off the chip*/
+    void  (*ssr_cleanup)(int reason);
 } bt_vendor_interface_t;
 
 
diff --git a/hci/include/hci_hal.h b/hci/include/hci_hal.h
index 93d9a2f..454c8ed 100644
--- a/hci/include/hci_hal.h
+++ b/hci/include/hci_hal.h
@@ -75,6 +75,9 @@
   // This is safe in the bluetooth context, because there is always a buffer
   // header that prefixes data you're sending.
   uint16_t (*transmit_data)(serial_data_type_t type, uint8_t *data, uint16_t length);
+
+  // to detect the SSR in PR controller
+  bool (*dev_in_reset)(void);
 } hci_hal_t;
 
 // Gets the correct hal implementation, as compiled for.
diff --git a/hci/include/hci_internals.h b/hci/include/hci_internals.h
index 6b9fb01..e92af5e 100644
--- a/hci/include/hci_internals.h
+++ b/hci/include/hci_internals.h
@@ -18,6 +18,14 @@
 
 #pragma once
 
+#define REMOVE_EAGER_THREADS TRUE
+
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+#include "osi/include/allocator.h"
+#include "osi/include/thread.h"
+#include "osi/include/reactor.h"
+#endif
+
 // 2 bytes for opcode, 1 byte for parameter length (Volume 2, Part E, 5.4.1)
 #define HCI_COMMAND_PREAMBLE_SIZE 3
 // 2 bytes for handle, 2 bytes for data length (Volume 2, Part E, 5.4.2)
@@ -26,3 +34,31 @@
 #define HCI_SCO_PREAMBLE_SIZE 3
 // 1 byte for event code, 1 byte for parameter length (Volume 2, Part E, 5.4.4)
 #define HCI_EVENT_PREAMBLE_SIZE 2
+
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+struct hci_reader_t {
+  int inbound_fd;
+
+  const allocator_t *allocator;
+  size_t buffer_size;
+  uint8_t *data_buffer;
+  int rd_ptr;
+  int wr_ptr;
+
+  thread_t *inbound_read_thread;
+  reactor_object_t *inbound_read_object;
+};
+typedef  struct hci_reader_t hci_reader_t;
+typedef void (*hci_reader_cb)(void *context);
+
+hci_reader_t *hci_reader_new(
+    int fd_to_read,
+    size_t buffer_size,
+    size_t max_buffer_count,
+    thread_t *thread,
+    hci_reader_cb read_cb
+    );
+
+size_t hci_reader_read(hci_reader_t *reader, uint8_t *buffer, size_t max_size);
+void hci_reader_free(hci_reader_t *reader);
+#endif
diff --git a/hci/include/hci_layer.h b/hci/include/hci_layer.h
index 54e1e4a..aba7c09 100644
--- a/hci/include/hci_layer.h
+++ b/hci/include/hci_layer.h
@@ -98,6 +98,11 @@
 
   // Send some data downward through the HCI layer
   void (*transmit_downward)(data_dispatcher_type_t type, void *data);
+
+  /** SSR cleanup is used in HW reset cases
+  ** which would close all the client channels
+  ** and turns off the chip*/
+  void (*ssr_cleanup)(int reason);
 } hci_t;
 
 const hci_t *hci_layer_get_interface();
diff --git a/hci/include/hci_packet_factory.h b/hci/include/hci_packet_factory.h
index ac6f12a..a6520ba 100644
--- a/hci/include/hci_packet_factory.h
+++ b/hci/include/hci_packet_factory.h
@@ -38,9 +38,11 @@
   BT_HDR *(*make_ble_read_supported_states)(void);
   BT_HDR *(*make_ble_read_local_supported_features)(void);
   BT_HDR *(*make_ble_read_resolving_list_size)(void);
+  BT_HDR *(*make_ble_read_adv_ext_size)(void);
   BT_HDR *(*make_ble_read_suggested_default_data_length)(void);
   BT_HDR *(*make_ble_set_event_mask)(const bt_event_mask_t *event_mask);
   BT_HDR *(*make_read_local_supported_codecs)(void);
+  BT_HDR *(*make_ble_read_offload_features_support)(void);
 } hci_packet_factory_t;
 
 const hci_packet_factory_t *hci_packet_factory_get_interface();
diff --git a/hci/include/hci_packet_parser.h b/hci/include/hci_packet_parser.h
index ba3b193..b83a71f 100644
--- a/hci/include/hci_packet_parser.h
+++ b/hci/include/hci_packet_parser.h
@@ -87,6 +87,11 @@
     uint8_t *resolving_list_size_ptr
   );
 
+  void (*parse_ble_read_adv_ext_size_response) (
+    BT_HDR *response,
+    uint8_t *ble_adv_ext_size
+  );
+
   void (*parse_ble_read_suggested_default_data_length_response)(
     BT_HDR *response,
     uint16_t *ble_default_packet_length_ptr
@@ -96,6 +101,10 @@
     BT_HDR *response,
     uint8_t *number_of_local_supported_codecs, uint8_t *local_supported_codecs);
 
+  void (*parse_ble_read_offload_features_response)(
+    BT_HDR *response,
+    bool *ble_offload_features_supported);
+
 } hci_packet_parser_t;
 
 const hci_packet_parser_t *hci_packet_parser_get_interface();
diff --git a/hci/include/low_power_manager.h b/hci/include/low_power_manager.h
index 95f990a..138b3eb 100644
--- a/hci/include/low_power_manager.h
+++ b/hci/include/low_power_manager.h
@@ -41,6 +41,9 @@
   // Tell the low power manager that you're done transmitting data. Must be
   // called on the thread provided at initialization time.
   void (*transmit_done)(void);
+
+  void (*start_idle_timer)(bool check_LPM);
+  void (*stop_idle_timer)();
 } low_power_manager_t;
 
 const low_power_manager_t *low_power_manager_get_interface();
diff --git a/hci/include/vendor.h b/hci/include/vendor.h
index e147b23..791c3da 100644
--- a/hci/include/vendor.h
+++ b/hci/include/vendor.h
@@ -68,6 +68,11 @@
 
   // Registers a callback for an asynchronous vendor-specific command.
   void (*set_callback)(vendor_async_opcode_t opcode, vendor_cb callback);
+
+  /** SSR cleanup is used in HW reset cases
+  ** which would close all the client channels
+  ** and turns off the chip*/
+  void (*ssr_cleanup) (int reason);
 } vendor_t;
 
 const vendor_t *vendor_get_interface();
diff --git a/hci/src/btsnoop.c b/hci/src/btsnoop.c
index dbc9bb2..88c37f7 100644
--- a/hci/src/btsnoop.c
+++ b/hci/src/btsnoop.c
@@ -20,6 +20,7 @@
 
 #include <arpa/inet.h>
 #include <assert.h>
+#include <cutils/properties.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
@@ -29,8 +30,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <sys/stat.h>
 #include <sys/time.h>
+#include <sys/poll.h>
 #include <unistd.h>
 
 #include "bt_types.h"
@@ -51,6 +54,19 @@
 static const uint64_t BTSNOOP_EPOCH_DELTA = 0x00dcddb30f2f8000ULL;
 
 static const stack_config_t *stack_config;
+extern int client_socket_btsnoop;
+static long int gmt_offset;
+#define USEC_PER_SEC 1000000L
+#define MAX_SNOOP_BUF_SIZE 1200
+
+// External BT snoop
+bool hci_ext_dump_enabled = false;
+
+/* snoop config from the config file, required for userdebug
+   build where snoop is enabled by default.
+   power/perf measurements need the snoop to be disabled.
+*/
+bool btsnoop_conf_from_file = false;
 
 static int logfile_fd = INVALID_FD;
 static bool module_started;
@@ -68,7 +84,20 @@
 // Module lifecycle functions
 
 static future_t *start_up(void) {
+  time_t t = time(NULL);
+  struct tm tm_cur;
+
+  localtime_r (&t, &tm_cur);
+  LOG_INFO(LOG_TAG, "%s Time GMT offset %ld\n", __func__, tm_cur.tm_gmtoff);
+  gmt_offset = tm_cur.tm_gmtoff;
+
   module_started = true;
+  stack_config->get_btsnoop_ext_options(&hci_ext_dump_enabled, &btsnoop_conf_from_file);
+#ifdef BLUEDROID_DEBUG
+  if (btsnoop_conf_from_file == false) {
+    hci_ext_dump_enabled = true;
+  }
+#endif
   update_logging();
 
   return NULL;
@@ -76,6 +105,9 @@
 
 static future_t *shut_down(void) {
   module_started = false;
+  if (hci_ext_dump_enabled == true) {
+    STOP_SNOOP_LOGGING();
+  }
   update_logging();
 
   return NULL;
@@ -141,17 +173,19 @@
 static uint64_t btsnoop_timestamp(void) {
   struct timeval tv;
   gettimeofday(&tv, NULL);
+  tv.tv_sec += gmt_offset;
 
   // Timestamp is in microseconds.
-  uint64_t timestamp = tv.tv_sec * 1000 * 1000LL;
+  uint64_t timestamp = ((uint64_t)tv.tv_sec) * 1000 * 1000LL;
   timestamp += tv.tv_usec;
   timestamp += BTSNOOP_EPOCH_DELTA;
   return timestamp;
 }
 
 static void update_logging() {
+  bool btsnoop_log_output = stack_config->get_btsnoop_turned_on();
   bool should_log = module_started &&
-    (logging_enabled_via_api || stack_config->get_btsnoop_turned_on());
+    (logging_enabled_via_api || btsnoop_log_output || hci_ext_dump_enabled);
 
   if (should_log == is_logging)
     return;
@@ -159,6 +193,14 @@
   is_logging = should_log;
   if (should_log) {
     btsnoop_net_open();
+#ifdef BLUEDROID_DEBUG
+    if(!btsnoop_log_output)
+#endif
+    {
+      if (logging_enabled_via_api || hci_ext_dump_enabled == true) {
+        START_SNOOP_LOGGING();
+      }
+    }
 
     const char *log_path = stack_config->get_btsnoop_log_path();
 
@@ -192,17 +234,37 @@
 }
 
 static void btsnoop_write(const void *data, size_t length) {
+  if (client_socket_btsnoop != -1) {
+    btsnoop_net_write(data, length);
+    /* skip writing to file if external client is connected*/
+    return;
+  }
+
   if (logfile_fd != INVALID_FD)
     write(logfile_fd, data, length);
-
-  btsnoop_net_write(data, length);
 }
 
+#ifdef DEBUG_SNOOP
+static uint64_t time_now_us() {
+    struct timespec ts_now;
+    clock_gettime(CLOCK_BOOTTIME, &ts_now);
+    return ((uint64_t)ts_now.tv_sec * USEC_PER_SEC) + ((uint64_t)ts_now.tv_nsec / 1000);
+}
+#endif
+
 static void btsnoop_write_packet(packet_type_t type, const uint8_t *packet, bool is_received) {
   int length_he = 0;
   int length;
   int flags;
   int drops = 0;
+  struct pollfd pfd;
+#ifdef DEBUG_SNOOP
+  uint64_t ts_begin;
+  uint64_t ts_end, ts_diff;
+#endif
+  uint8_t snoop_buf[MAX_SNOOP_BUF_SIZE] = {0};
+  uint32_t offset = 0;
+
   switch (type) {
     case kCommandPacket:
       length_he = packet[2] + 4;
@@ -232,12 +294,73 @@
   time_hi = htonl(time_hi);
   time_lo = htonl(time_lo);
 
-  btsnoop_write(&length, 4);
-  btsnoop_write(&length, 4);
-  btsnoop_write(&flags, 4);
-  btsnoop_write(&drops, 4);
-  btsnoop_write(&time_hi, 4);
-  btsnoop_write(&time_lo, 4);
-  btsnoop_write(&type, 1);
-  btsnoop_write(packet, length_he - 1);
+  /* store the length in both original and included fields */
+  memcpy(snoop_buf + offset, &length, 4);
+  offset += 4;
+  memcpy(snoop_buf + offset, &length, 4);
+  offset += 4;
+
+  /* flags:  */
+  memcpy(snoop_buf + offset, &flags, 4);
+  offset += 4;
+
+  /* drops: none */
+  memcpy(snoop_buf + offset, &drops, 4);
+  offset += 4;
+
+  /* time */
+  memcpy(snoop_buf + offset, &time_hi, 4);
+  offset += 4;
+  memcpy(snoop_buf + offset, &time_lo, 4);
+  offset = offset + 4;
+
+  snoop_buf[offset] = type;
+  offset += 1;
+  if (offset + length_he + 1 > MAX_SNOOP_BUF_SIZE) {
+    LOG_ERROR(LOG_TAG, "Bad packet length, downgrading the length to %d from %d",
+                                      MAX_SNOOP_BUF_SIZE - offset - 1, length_he);
+    length_he = MAX_SNOOP_BUF_SIZE - offset - 1;
+  }
+  memcpy(snoop_buf + offset, packet, length_he - 1);
+
+  if (client_socket_btsnoop != -1) {
+    pfd.fd = client_socket_btsnoop;
+    pfd.events = POLLOUT;
+#ifdef DEBUG_SNOOP
+    ts_begin = time_now_us();
+#endif
+
+    if (poll(&pfd, 1, 10) == 0) {
+      LOG_ERROR(LOG_TAG, "btsnoop poll : Taking more than 10 ms : skip dump");
+#ifdef DEBUG_SNOOP
+      ts_end = time_now_us();
+      ts_diff = ts_end - ts_begin;
+      if (ts_diff > 10000) {
+        LOG_ERROR(LOG_TAG, "btsnoop poll T/O : took more time %08lld us", ts_diff);
+      }
+#endif
+      return;
+    }
+
+#ifdef DEBUG_SNOOP
+    ts_end = time_now_us();
+    ts_diff = ts_end - ts_begin;
+    if (ts_diff > 10000) {
+      LOG_ERROR(LOG_TAG, "btsnoop poll : took more time %08lld us", ts_diff);
+    }
+#endif
+  }
+#ifdef DEBUG_SNOOP
+  ts_begin = time_now_us();
+#endif
+
+  btsnoop_write(snoop_buf, offset + length_he - 1);
+
+#ifdef DEBUG_SNOOP
+  ts_end = time_now_us();
+  ts_diff = ts_end - ts_begin;
+  if (ts_diff > 10000) {
+    LOG_ERROR(LOG_TAG, "btsnoop write : Write took more time %08lld us", ts_diff);
+  }
+#endif
 }
diff --git a/hci/src/btsnoop_net.c b/hci/src/btsnoop_net.c
index 0bfad4e..274b546 100644
--- a/hci/src/btsnoop_net.c
+++ b/hci/src/btsnoop_net.c
@@ -19,6 +19,9 @@
 #define LOG_TAG "bt_snoop_net"
 
 #include <assert.h>
+#include <cutils/sockets.h>
+#include <sys/un.h>
+#include <sys/poll.h>
 #include <errno.h>
 #include <netinet/in.h>
 #include <pthread.h>
@@ -43,12 +46,37 @@
 static bool listen_thread_valid_ = false;
 static pthread_mutex_t client_socket_lock_ = PTHREAD_MUTEX_INITIALIZER;
 static int listen_socket_ = -1;
-static int client_socket_ = -1;
+int client_socket_btsnoop = -1;
+
+/*
+    local socket for writing from different process
+    to limit blocking of HCI threads.
+*/
+#define LOCAL_SOCKET_NAME "bthcitraffic"
+static int listen_socket_local_ = -1;
+
+static int local_socket_create(void) {
+
+  listen_socket_local_ = socket(AF_LOCAL, SOCK_STREAM, 0);
+  if(listen_socket_local_ < 0) {
+    return -1;
+  }
+
+  if(socket_local_server_bind(listen_socket_local_, LOCAL_SOCKET_NAME,
+      ANDROID_SOCKET_NAMESPACE_ABSTRACT) < 0) {
+    LOG_ERROR(LOG_TAG, "Failed to create Local Socket (%s)", strerror(errno));
+    return -1;
+  }
+
+  if (listen(listen_socket_local_, 1) < 0) {
+    LOG_ERROR(LOG_TAG, "Local socket listen failed (%s)", strerror(errno));
+    close(listen_socket_local_);
+    return -1;
+  }
+  return listen_socket_local_;
+}
 
 void btsnoop_net_open() {
-#if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE))
-  return;               // Disable using network sockets for security reasons
-#endif
 
   listen_thread_valid_ = (pthread_create(&listen_thread_, NULL, listen_fn_, NULL) == 0);
   if (!listen_thread_valid_) {
@@ -59,44 +87,55 @@
 }
 
 void btsnoop_net_close() {
-#if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE))
-  return;               // Disable using network sockets for security reasons
-#endif
 
   if (listen_thread_valid_) {
+#if (defined(BT_NET_DEBUG) && (NET_DEBUG == TRUE))
+    // Disable using network sockets for security reasons
     shutdown(listen_socket_, SHUT_RDWR);
+#endif
+    shutdown(listen_socket_local_, SHUT_RDWR);
     pthread_join(listen_thread_, NULL);
-    safe_close_(&client_socket_);
+    safe_close_(&client_socket_btsnoop);
     listen_thread_valid_ = false;
   }
 }
 
 void btsnoop_net_write(const void *data, size_t length) {
-#if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE))
-  return;               // Disable using network sockets for security reasons
-#endif
+  ssize_t ret;
 
   pthread_mutex_lock(&client_socket_lock_);
-  if (client_socket_ != -1) {
-    ssize_t ret;
-    OSI_NO_INTR(ret = send(client_socket_, data, length, 0));
-
-    if (ret == -1 && errno == ECONNRESET) {
-      safe_close_(&client_socket_);
-    }
+  if (client_socket_btsnoop != -1) {
+    do {
+      if ((ret = send(client_socket_btsnoop, data, length, 0)) == -1 && errno == ECONNRESET) {
+        safe_close_(&client_socket_btsnoop);
+        LOG_INFO(LOG_TAG, "%s conn closed", __func__);
+      }
+      if ((size_t) ret < length) {
+        LOG_ERROR(LOG_TAG, "%s: send : not able to write complete packet", __func__);
+      }
+      length -= ret;
+    } while ((length > 0) && (ret != -1));
   }
+
   pthread_mutex_unlock(&client_socket_lock_);
 }
 
 static void *listen_fn_(UNUSED_ATTR void *context) {
+  fd_set sock_fds;
+  int fd_max = -1, retval;
 
   prctl(PR_SET_NAME, (unsigned long)LISTEN_THREAD_NAME_, 0, 0, 0);
 
+  FD_ZERO(&sock_fds);
+
+  // Disable using network sockets for security reasons
   listen_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   if (listen_socket_ == -1) {
     LOG_ERROR(LOG_TAG, "%s socket creation failed: %s", __func__, strerror(errno));
     goto cleanup;
   }
+  FD_SET(listen_socket_, &sock_fds);
+  fd_max = listen_socket_;
 
   int enable = 1;
   if (setsockopt(listen_socket_, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) == -1) {
@@ -118,29 +157,73 @@
     goto cleanup;
   }
 
+  if (local_socket_create() != -1) {
+    if (listen_socket_local_ > fd_max) {
+      fd_max = listen_socket_local_;
+    }
+    FD_SET(listen_socket_local_, &sock_fds);
+  }
+
+  if (fd_max == -1) {
+    LOG_ERROR(LOG_TAG, "%s No sockets to wait for conn..", __func__);
+    return NULL;
+  }
+
   for (;;) {
-    int client_socket;
-    OSI_NO_INTR(client_socket = accept(listen_socket_, NULL, NULL));
-    if (client_socket == -1) {
-      if (errno == EINVAL || errno == EBADF) {
-        break;
+    int client_socket = -1;
+
+    LOG_DEBUG(LOG_TAG, "waiting for client connection");
+
+    if ((retval = select(fd_max + 1, &sock_fds, NULL, NULL, NULL)) == -1) {
+      LOG_ERROR(LOG_TAG, "%s select failed %s", __func__, strerror(errno));
+      goto cleanup;
+    }
+
+    if ((listen_socket_ != -1) && FD_ISSET(listen_socket_, &sock_fds)) {
+      client_socket = accept(listen_socket_, NULL, NULL);
+      if (client_socket == -1) {
+        if (errno == EINVAL || errno == EBADF) {
+          LOG_WARN(LOG_TAG, "%s error accepting TCP socket: %s", __func__, strerror(errno));
+          break;
+        }
+        LOG_WARN(LOG_TAG, "%s error accepting TCP socket: %s", __func__, strerror(errno));
+        continue;
       }
-      LOG_WARN(LOG_TAG, "%s error accepting socket: %s", __func__, strerror(errno));
-      continue;
+    } else if ((listen_socket_local_ != -1) && FD_ISSET(listen_socket_local_, &sock_fds)){
+      struct sockaddr_un cliaddr;
+      int length;
+
+      client_socket = accept(listen_socket_local_, (struct sockaddr *)&cliaddr, (socklen_t *)&length);
+      if (client_socket == -1) {
+        if (errno == EINVAL || errno == EBADF) {
+          LOG_WARN(LOG_TAG, "%s error accepting LOCAL socket: %s", __func__, strerror(errno));
+          break;
+        }
+        LOG_WARN(LOG_TAG, "%s error accepting LOCAL socket: %s", __func__, strerror(errno));
+        continue;
+      }
     }
 
     /* When a new client connects, we have to send the btsnoop file header. This allows
        a decoder to treat the session as a new, valid btsnoop file. */
     pthread_mutex_lock(&client_socket_lock_);
-    safe_close_(&client_socket_);
-    client_socket_ = client_socket;
-
-    OSI_NO_INTR(send(client_socket_, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16, 0));
+    safe_close_(&client_socket_btsnoop);
+    client_socket_btsnoop = client_socket;
+    send(client_socket_btsnoop, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16, 0);
     pthread_mutex_unlock(&client_socket_lock_);
+
+    FD_ZERO(&sock_fds);
+    if(listen_socket_ != -1) {
+      FD_SET(listen_socket_, &sock_fds);
+    }
+    if(listen_socket_local_ != -1) {
+        FD_SET(listen_socket_local_, &sock_fds);
+    }
   }
 
 cleanup:
   safe_close_(&listen_socket_);
+  safe_close_(&listen_socket_local_);
   return NULL;
 }
 
diff --git a/hci/src/hci_hal.c b/hci/src/hci_hal.c
index fa526ce..8337695 100644
--- a/hci/src/hci_hal.c
+++ b/hci/src/hci_hal.c
@@ -15,14 +15,112 @@
  *  limitations under the License.
  *
  ******************************************************************************/
-
+#include <string.h>
 #include "hci_hal.h"
+#include "hci_internals.h"
+#include "bt_utils.h"
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+#include <assert.h>
+#include "osi/include/eager_reader.h"
+#include "osi/include/osi.h"
+#include "osi/include/log.h"
+#endif
+
+bt_soc_type soc_type;
 
 const hci_hal_t *hci_hal_get_interface() {
-#if HCI_USE_MCT
-  return hci_hal_mct_get_interface();
-#else
-  return hci_hal_h4_get_interface();
-#endif
+    soc_type = get_soc_type();
+
+    if (soc_type == BT_SOC_ROME || soc_type == BT_SOC_CHEROKEE) {
+        return hci_hal_h4_get_interface();
+    } else {
+        return hci_hal_mct_get_interface();
+    }
 }
 
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+void hci_reader_free(hci_reader_t *reader) {
+  if (!reader)
+    return;
+
+  // Only unregister from the input if we actually did register
+  if (reader->inbound_read_object)
+    reactor_unregister(reader->inbound_read_object);
+
+  // Free the current buffer, because it's not in the queue
+  // and won't be freed below
+  if (reader->data_buffer)
+    osi_free(reader->data_buffer);
+
+  osi_free(reader);
+}
+
+hci_reader_t *hci_reader_new(
+    int fd_to_read,
+    size_t buffer_size,
+    size_t max_buffer_count,
+    thread_t *thread,
+    hci_reader_cb read_cb
+    ) {
+
+  assert(fd_to_read != INVALID_FD);
+  assert(buffer_size > 0);
+  assert(max_buffer_count > 0);
+
+
+  hci_reader_t *ret = osi_calloc(sizeof(hci_reader_t));
+  if (!ret) {
+    LOG_ERROR("%s unable to allocate memory for new hci_reader.", __func__);
+    goto error;
+  }
+
+  ret->inbound_fd = fd_to_read;
+
+  ret->data_buffer = osi_calloc(buffer_size);
+  ret->buffer_size = buffer_size;
+  ret->rd_ptr = 0;
+  ret->wr_ptr = 0;
+
+  ret->inbound_read_thread = thread;
+  if (!ret->inbound_read_thread) {
+    LOG_ERROR("%s unable to make reading thread.", __func__);
+    goto error;
+  }
+
+  ret->inbound_read_object = reactor_register(
+      thread_get_reactor(ret->inbound_read_thread),
+      fd_to_read,
+      ret,
+      read_cb,
+      NULL
+      );
+
+  return ret;
+
+error:;
+  hci_reader_free(ret);
+  return NULL;
+}
+
+size_t hci_reader_read(hci_reader_t *reader, uint8_t *buffer, size_t req_size) {
+  int bytes_read = 0;
+  assert(reader != NULL);
+  assert(buffer != NULL);
+
+  // If the caller wants nonblocking behavior, poll to see if we have
+  // any bytes available before reading.
+  if (reader->rd_ptr < reader->wr_ptr) {
+    bytes_read = reader->wr_ptr - reader->rd_ptr;
+    if ((size_t) bytes_read > req_size)
+      bytes_read = req_size;
+    memcpy(buffer, reader->data_buffer+reader->rd_ptr, bytes_read);
+    reader->rd_ptr += bytes_read;
+  } else {
+    bytes_read = read(reader->inbound_fd, buffer, req_size);
+    if(bytes_read == -1)
+      bytes_read = 0;
+  }
+
+  return bytes_read;
+}
+#endif
diff --git a/hci/src/hci_hal_h4.c b/hci/src/hci_hal_h4.c
index 9c7afe5..a1a9b14 100644
--- a/hci/src/hci_hal_h4.c
+++ b/hci/src/hci_hal_h4.c
@@ -48,13 +48,23 @@
 static thread_t *thread; // Not owned by us
 
 static int uart_fd;
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static hci_reader_t *uart_stream;
+#else
 static eager_reader_t *uart_stream;
+#endif
 static serial_data_type_t current_data_type;
 static bool stream_has_interpretation;
 static bool stream_corruption_detected;
 static uint8_t stream_corruption_bytes_to_ignore;
 
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static void event_uart_has_bytes(void *context);
+#else
 static void event_uart_has_bytes(eager_reader_t *reader, void *context);
+static bool stream_corrupted_during_le_scan_workaround(const uint8_t byte_read);
+#endif
+
 
 // Interface functions
 
@@ -85,20 +95,28 @@
     goto error;
   }
 
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  uart_stream = hci_reader_new(uart_fd, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, thread, event_uart_has_bytes);
+  if (!uart_stream) {
+    LOG_ERROR("%s unable to create hci reader for the uart serial port.", __func__);
+    goto error;
+  }
+#else
   uart_stream = eager_reader_new(uart_fd, &allocator_malloc, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, "hci_single_channel");
   if (!uart_stream) {
     LOG_ERROR(LOG_TAG, "%s unable to create eager reader for the uart serial port.", __func__);
     goto error;
   }
+  eager_reader_register(uart_stream, thread_get_reactor(thread), event_uart_has_bytes, NULL);
+  thread_set_priority(eager_reader_get_read_thread(uart_stream), HCI_THREAD_PRIORITY);
+#endif
 
   stream_has_interpretation = false;
   stream_corruption_detected = false;
   stream_corruption_bytes_to_ignore = 0;
-  eager_reader_register(uart_stream, thread_get_reactor(thread), event_uart_has_bytes, NULL);
 
   // Raise thread priorities to keep up with audio
   thread_set_priority(thread, HCI_THREAD_PRIORITY);
-  thread_set_priority(eager_reader_get_read_thread(uart_stream), HCI_THREAD_PRIORITY);
 
   return true;
 
@@ -110,7 +128,13 @@
 static void hal_close() {
   LOG_INFO(LOG_TAG, "%s", __func__);
 
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  hci_reader_free(uart_stream);
+#else
   eager_reader_free(uart_stream);
+#endif
+  uart_stream = NULL;
+
   vendor->send_command(VENDOR_CLOSE_USERIAL, NULL);
   uart_fd = INVALID_FD;
 }
@@ -127,16 +151,38 @@
     return 0;
   }
 
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  return hci_reader_read(uart_stream, buffer, max_size);
+#else
   return eager_reader_read(uart_stream, buffer, max_size);
+#endif
 }
 
 static void packet_finished(serial_data_type_t type) {
-  if (!stream_has_interpretation)
+  if (!stream_has_interpretation) {
     LOG_ERROR(LOG_TAG, "%s with no existing stream interpretation.", __func__);
-  else if (current_data_type != type)
+  } else if (current_data_type != type) {
     LOG_ERROR(LOG_TAG, "%s with different type than existing interpretation.", __func__);
+  }
 
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  if (uart_stream->rd_ptr == uart_stream->wr_ptr) {
+    uart_stream->rd_ptr = uart_stream->wr_ptr = 0;
+    stream_has_interpretation = false;
+  } else {
+    uint8_t type_byte;
+    type_byte = uart_stream->data_buffer[uart_stream->rd_ptr++];
+    if (type_byte < DATA_TYPE_ACL || type_byte > DATA_TYPE_EVENT) {
+      LOG_ERROR("%s Unknown HCI message type. Dropping this byte 0x%x, min %x, max %x", __func__,
+                                                    type_byte, DATA_TYPE_ACL, DATA_TYPE_EVENT);
+      return;
+    }
+    current_data_type = type_byte;
+    callbacks->data_ready(current_data_type);
+  }
+#else
   stream_has_interpretation = false;
+#endif
 }
 
 static uint16_t transmit_data(serial_data_type_t type, uint8_t *data, uint16_t length) {
@@ -184,6 +230,11 @@
   return transmitted_length;
 }
 
+static bool hal_dev_in_reset()
+{
+    return false;
+}
+
 // Internal functions
 
 // WORKAROUND:
@@ -194,6 +245,7 @@
 // skip the correct amount of bytes in the stream to re-synchronize onto
 // a packet boundary.
 // Function returns true if |byte_read| has been processed by the workaround.
+#if (!defined(REMOVE_EAGER_THREADS) || ((defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == FALSE))))
 static bool stream_corrupted_during_le_scan_workaround(const uint8_t byte_read)
 {
   if (!stream_corruption_detected && byte_read == HCI_BLE_EVENT) {
@@ -219,8 +271,35 @@
 
   return false;
 }
-
+#endif
 // See what data is waiting, and notify the upper layer
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static void event_uart_has_bytes(void *context) {
+  uint8_t type_byte;
+  int bytes_read;
+  hci_reader_t *reader = (hci_reader_t *) context;
+  bytes_read = read(reader->inbound_fd, reader->data_buffer + reader->wr_ptr, reader->buffer_size - reader->wr_ptr);
+
+  if (bytes_read <= 0)  {
+    LOG_ERROR("%s could not read HCI message type", __func__);
+    return;
+  }
+  reader->wr_ptr += bytes_read;
+  if (!stream_has_interpretation) {
+    type_byte = reader->data_buffer[reader->rd_ptr++];
+
+    if (type_byte < DATA_TYPE_ACL || type_byte > DATA_TYPE_EVENT) {
+      LOG_ERROR("%s Unknown HCI message type. Dropping this byte 0x%x, min %x, max %x", __func__, type_byte, DATA_TYPE_ACL, DATA_TYPE_EVENT);
+      return;
+    }
+
+    stream_has_interpretation = true;
+    current_data_type = type_byte;
+  }
+
+  callbacks->data_ready(current_data_type);
+}
+#else
 static void event_uart_has_bytes(eager_reader_t *reader, UNUSED_ATTR void *context) {
   if (stream_has_interpretation) {
     callbacks->data_ready(current_data_type);
@@ -246,6 +325,7 @@
     current_data_type = type_byte;
   }
 }
+#endif
 
 static const hci_hal_t interface = {
   hal_init,
@@ -256,6 +336,7 @@
   read_data,
   packet_finished,
   transmit_data,
+  hal_dev_in_reset
 };
 
 const hci_hal_t *hci_hal_h4_get_interface() {
diff --git a/hci/src/hci_hal_mct.c b/hci/src/hci_hal_mct.c
index 669a9f8..2406567 100644
--- a/hci/src/hci_hal_mct.c
+++ b/hci/src/hci_hal_mct.c
@@ -33,6 +33,9 @@
 
 #define HCI_HAL_SERIAL_BUFFER_SIZE 1026
 
+#include <termios.h>
+#include <sys/ioctl.h>
+
 // Our interface and modules we import
 static const hci_hal_t interface;
 static const hci_hal_callbacks_t *callbacks;
@@ -41,12 +44,22 @@
 static thread_t *thread; // Not owned by us
 
 static int uart_fds[CH_MAX];
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static hci_reader_t *event_stream;
+static hci_reader_t *acl_stream;
+#else
 static eager_reader_t *event_stream;
 static eager_reader_t *acl_stream;
+#endif
 
 static uint16_t transmit_data_on(int fd, uint8_t *data, uint16_t length);
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static void event_event_stream_has_bytes(void *context);
+static void event_acl_stream_has_bytes(void *context);
+#else
 static void event_event_stream_has_bytes(eager_reader_t *reader, void *context);
 static void event_acl_stream_has_bytes(eager_reader_t *reader, void *context);
+#endif
 
 // Interface functions
 
@@ -93,6 +106,21 @@
     goto error;
   }
 
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  event_stream = hci_reader_new(uart_fds[CH_EVT], HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX,
+                                                 thread, event_event_stream_has_bytes);
+  if (!event_stream) {
+    LOG_ERROR("%s unable to create hci reader for the event uart serial port.", __func__);
+    goto error;
+  }
+
+  acl_stream = hci_reader_new(uart_fds[CH_ACL_IN], HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX,
+                                                    thread, event_acl_stream_has_bytes);
+  if (!acl_stream) {
+    LOG_ERROR("%s unable to create hci reader for the acl-in uart serial port.", __func__);
+    goto error;
+  }
+#else
   event_stream = eager_reader_new(uart_fds[CH_EVT], &allocator_malloc, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, "hci_mct");
   if (!event_stream) {
     LOG_ERROR(LOG_TAG, "%s unable to create eager reader for the event uart serial port.", __func__);
@@ -108,6 +136,8 @@
   eager_reader_register(event_stream, thread_get_reactor(thread), event_event_stream_has_bytes, NULL);
   eager_reader_register(acl_stream, thread_get_reactor(thread), event_acl_stream_has_bytes, NULL);
 
+#endif
+
   return true;
 
 error:;
@@ -118,20 +148,66 @@
 static void hal_close() {
   LOG_INFO(LOG_TAG, "%s", __func__);
 
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  hci_reader_free(event_stream);
+  event_stream = NULL;
+  hci_reader_free(acl_stream);
+  acl_stream = NULL;
+#else
   eager_reader_free(event_stream);
+  event_stream = NULL;
+
   eager_reader_free(acl_stream);
+  acl_stream = NULL;
+#endif
+
   vendor->send_command(VENDOR_CLOSE_USERIAL, NULL);
 
   for (int i = 0; i < CH_MAX; i++)
     uart_fds[i] = INVALID_FD;
 }
 
+static bool hal_dev_in_reset()
+{
+  volatile int serial_bits;
+  bool dev_reset_done =0;
+  uint8_t retry_count = 0;
+  ioctl(uart_fds[CH_EVT], TIOCMGET, &serial_bits);
+  if (serial_bits & TIOCM_OUT2) {
+    while(serial_bits & TIOCM_OUT1) {
+      LOG_WARN(LOG_TAG,"userial_device in reset \n");
+      sleep(2);
+      retry_count++;
+      ioctl(uart_fds[CH_EVT], TIOCMGET, &serial_bits);
+      if((serial_bits & TIOCM_OUT1))
+        dev_reset_done = 0;
+      else
+        dev_reset_done = 1;
+      if(retry_count == 6) {
+        //treat it as ssr completed to kill the bt
+        // process
+        dev_reset_done = 1;
+        break;
+      }
+    }
+  }
+  return dev_reset_done;
+}
+
 static size_t read_data(serial_data_type_t type, uint8_t *buffer, size_t max_size) {
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  if (type == DATA_TYPE_ACL) {
+    return hci_reader_read(acl_stream, buffer, max_size);
+  } else if (type == DATA_TYPE_EVENT) {
+    return hci_reader_read(event_stream, buffer, max_size);
+  }
+#else
   if (type == DATA_TYPE_ACL) {
     return eager_reader_read(acl_stream, buffer, max_size);
   } else if (type == DATA_TYPE_EVENT) {
     return eager_reader_read(event_stream, buffer, max_size);
   }
+#endif
 
   LOG_ERROR(LOG_TAG, "%s invalid data type: %d", __func__, type);
   return 0;
@@ -139,6 +215,25 @@
 
 static void packet_finished(UNUSED_ATTR serial_data_type_t type) {
   // not needed by this protocol
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  hci_reader_t *stream = NULL;
+  if (type == DATA_TYPE_ACL) {
+    stream = acl_stream;
+  } else if (type == DATA_TYPE_EVENT) {
+    stream = event_stream;
+  }
+
+  if(!stream) {
+    LOG_ERROR("%s invalid data type: %d", __func__, type);
+    return;
+  }
+
+  if (stream->rd_ptr == stream->wr_ptr) {
+    stream->rd_ptr = stream->wr_ptr = 0;
+  } else {
+    callbacks->data_ready(type);
+  }
+#endif
 }
 
 static uint16_t transmit_data(serial_data_type_t type, uint8_t *data, uint16_t length) {
@@ -180,14 +275,45 @@
   return transmitted_length;
 }
 
-static void event_event_stream_has_bytes(UNUSED_ATTR eager_reader_t *reader, UNUSED_ATTR void *context) {
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static void event_event_stream_has_bytes(void *context) {
+  int bytes_read;
+  hci_reader_t *reader = (hci_reader_t *) context;
+  bytes_read = read(reader->inbound_fd, reader->data_buffer+reader->wr_ptr,
+                                    reader->buffer_size - reader->wr_ptr);
+  if (bytes_read <= 0) {
+    LOG_ERROR("%s could not read HCI message type", __func__);
+    return;
+  }
+  reader->wr_ptr += bytes_read;
   callbacks->data_ready(DATA_TYPE_EVENT);
 }
+#else
+static void event_event_stream_has_bytes(UNUSED_ATTR eager_reader_t *reader, UNUSED_ATTR void *context) {
+   callbacks->data_ready(DATA_TYPE_EVENT);
+}
+#endif
 
-static void event_acl_stream_has_bytes(UNUSED_ATTR eager_reader_t *reader, UNUSED_ATTR void *context) {
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static void event_acl_stream_has_bytes(void *context) {
   // No real concept of incoming SCO typed data, just ACL
+  int bytes_read;
+  hci_reader_t *reader = (hci_reader_t *) context;
+  bytes_read = read(reader->inbound_fd, reader->data_buffer+reader->wr_ptr,
+                                  reader->buffer_size - reader->wr_ptr);
+  if (bytes_read <= 0) {
+    LOG_ERROR("%s could not read HCI message type", __func__);
+    return;
+  }
+  reader->wr_ptr += bytes_read;
   callbacks->data_ready(DATA_TYPE_ACL);
 }
+#else
+static void event_acl_stream_has_bytes(UNUSED_ATTR eager_reader_t *reader, UNUSED_ATTR void *context) {
+   // No real concept of incoming SCO typed data, just ACL
+   callbacks->data_ready(DATA_TYPE_ACL);
+}
+#endif
 
 static const hci_hal_t interface = {
   hal_init,
@@ -198,6 +324,7 @@
   read_data,
   packet_finished,
   transmit_data,
+  hal_dev_in_reset
 };
 
 const hci_hal_t *hci_hal_mct_get_interface() {
diff --git a/hci/src/hci_layer.c b/hci/src/hci_layer.c
index 3a45135..0b7e35a 100644
--- a/hci/src/hci_layer.c
+++ b/hci/src/hci_layer.c
@@ -80,6 +80,12 @@
   FINISHED
 } receive_state_t;
 
+typedef enum {
+  HCI_SHUTDOWN,
+  HCI_STARTED,
+  HCI_READY
+} hci_layer_state;
+
 typedef struct {
   receive_state_t state;
   uint16_t bytes_remaining;
@@ -97,13 +103,33 @@
   BT_HDR *command;
 } waiting_command_t;
 
+typedef enum {
+    BT_SOC_DEFAULT = 0,
+    BT_SOC_SMD = BT_SOC_DEFAULT,
+    BT_SOC_AR3K,
+    BT_SOC_ROME,
+    BT_SOC_CHEROKEE,
+    /* Add chipset type here */
+    BT_SOC_RESERVED
+} bt_soc_type;
+
+typedef enum {
+  LPM_CONFIG_ALL,
+  LPM_CONFIG_TX,
+  LPM_CONFIG_NONE
+} low_power_config_t;
+
 // Using a define here, because it can be stringified for the property lookup
 #define DEFAULT_STARTUP_TIMEOUT_MS 8000
 #define STRING_VALUE_OF(x) #x
 
+low_power_config_t lpm_config = LPM_CONFIG_NONE;
+
 static const uint32_t EPILOG_TIMEOUT_MS = 3000;
 static const uint32_t COMMAND_PENDING_TIMEOUT_MS = 8000;
 
+extern int soc_type;
+
 // Our interface
 static bool interface_created;
 static hci_t interface;
@@ -125,6 +151,7 @@
 static volatile bool firmware_is_configured = false;
 static alarm_t *epilog_timer;
 static alarm_t *startup_timer;
+static alarm_t *hardware_error_timer;
 
 // Outbound-related
 static int command_credits = 1;
@@ -134,12 +161,14 @@
 // Inbound-related
 static alarm_t *command_response_timer;
 static list_t *commands_pending_response;
+static list_t *commands_pending_in_queue;
 static pthread_mutex_t commands_pending_response_lock;
 static packet_receive_data_t incoming_packets[INBOUND_PACKET_TYPE_COUNT];
 
 // The hand-off point for data going to a higher layer, set by the higher layer
 static fixed_queue_t *upwards_data_queue;
 
+static int hci_state;
 static future_t *shut_down();
 
 static void event_finish_startup(void *context);
@@ -152,6 +181,7 @@
 static void event_epilog(void *context);
 static void epilog_finished_callback(bool success);
 static void epilog_timer_expired(void *context);
+static void hardware_error_timer_expired(void *context);
 
 static void event_command_ready(fixed_queue_t *queue, void *context);
 static void event_packet_ready(fixed_queue_t *queue, void *context);
@@ -164,6 +194,10 @@
 static waiting_command_t *get_waiting_command(command_opcode_t opcode);
 static void update_command_response_timer(void);
 
+static bool create_hw_reset_evt_packet(packet_receive_data_t *incoming);
+
+void ssr_cleanup (int reason);
+
 // Module lifecycle functions
 
 static future_t *start_up(void) {
@@ -175,6 +209,22 @@
   command_credits = 1;
   firmware_is_configured = false;
 
+  char prop_lpm_config[PROPERTY_VALUE_MAX];
+  osi_property_get("persist.service.bdroid.lpmcfg", prop_lpm_config, "all");
+  if (!strcmp(prop_lpm_config, "all")) {
+     // LPM configured for both Tx and Rx channels
+     lpm_config = LPM_CONFIG_ALL;
+  }
+  else if (!strcmp(prop_lpm_config, "tx")) {
+     // LPM configured for Tx channel only
+     lpm_config = LPM_CONFIG_TX;
+  }
+  else {
+     lpm_config = LPM_CONFIG_NONE;
+  }
+
+  LOG_INFO(LOG_TAG, "%s lpm configure value = %d.", __func__, lpm_config);
+
   pthread_mutex_init(&commands_pending_response_lock, NULL);
 
   // TODO(armansito): cutils/properties.h is only being used to pull-in runtime
@@ -230,6 +280,11 @@
     LOG_ERROR(LOG_TAG, "%s unable to create list for commands pending response.", __func__);
     goto error;
   }
+  commands_pending_in_queue = list_new(NULL);
+  if (!commands_pending_in_queue) {
+    LOG_ERROR("%s unable to create list for commands pending response.", __func__);
+    goto error;
+  }
 
   memset(incoming_packets, 0, sizeof(incoming_packets));
 
@@ -273,6 +328,7 @@
 
   LOG_DEBUG(LOG_TAG, "%s starting async portion", __func__);
   thread_post(thread, event_finish_startup, NULL);
+  hci_state = HCI_STARTED;
   return local_startup_future;
 
 error:
@@ -296,12 +352,16 @@
     thread_join(thread);
   }
 
+  hci_state = HCI_SHUTDOWN;
+
   fixed_queue_free(command_queue, osi_free);
   command_queue = NULL;
   fixed_queue_free(packet_queue, buffer_allocator->free);
   packet_queue = NULL;
   list_free(commands_pending_response);
   commands_pending_response = NULL;
+  list_free(commands_pending_in_queue);
+  commands_pending_in_queue = NULL;
 
   pthread_mutex_destroy(&commands_pending_response_lock);
 
@@ -358,6 +418,11 @@
     command_complete_cb complete_callback,
     command_status_cb status_callback,
     void *context) {
+  if (hci_state < HCI_STARTED) {
+    LOG_ERROR("%s Returning, hci_layer not ready", __func__);
+    return;
+  }
+
   waiting_command_t *wait_entry = osi_calloc(sizeof(waiting_command_t));
 
   uint8_t *stream = command->data + command->offset;
@@ -395,9 +460,14 @@
   if (type == MSG_STACK_TO_HC_HCI_CMD) {
     // TODO(zachoverflow): eliminate this call
     transmit_command((BT_HDR *)data, NULL, NULL, NULL);
-    LOG_WARN(LOG_TAG, "%s legacy transmit of command. Use transmit_command instead.", __func__);
+    LOG_WARN("%s legacy transmit of command. Use transmit_command instead.", __func__);
   } else {
+    if (hci_state < HCI_STARTED) {
+      LOG_ERROR("%s Returning, hci_layer not ready", __func__);
+      return;
+    } else {
     fixed_queue_enqueue(packet_queue, data);
+    }
   }
 }
 
@@ -471,28 +541,64 @@
   thread_stop(thread);
 }
 
-// Command/packet transmitting functions
+static void hardware_error_timer_expired(UNUSED_ATTR void *context) {
+  LOG_INFO("%s", __func__);
+  alarm_free(hardware_error_timer);
+  hardware_error_timer = NULL;
+  ssr_cleanup(0x33);//SSR reason 0x33 = HW ERR EVT
+  usleep(20000);
+  kill(getpid(), SIGKILL);
+}
 
-static void event_command_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) {
-  if (command_credits > 0) {
-    waiting_command_t *wait_entry = fixed_queue_dequeue(queue);
-    command_credits--;
-
-    // Move it to the list of commands awaiting response
+static void send_cmd_to_lower(waiting_command_t *wait_entry) {
+  // Move it to the list of commands awaiting response
     pthread_mutex_lock(&commands_pending_response_lock);
     list_append(commands_pending_response, wait_entry);
     pthread_mutex_unlock(&commands_pending_response_lock);
 
     // Send it off
-    low_power_manager->wake_assert();
+    if (LPM_CONFIG_TX == lpm_config) {
+        low_power_manager->stop_idle_timer();;
+    }
+    else {
+        low_power_manager->wake_assert();
+    }
+
+    if (LPM_CONFIG_TX == lpm_config) {
+        low_power_manager->start_idle_timer(false);
+    }
+    else {
+        low_power_manager->transmit_done();
+    }
+
     packet_fragmenter->fragment_and_dispatch(wait_entry->command);
-    low_power_manager->transmit_done();
 
     update_command_response_timer();
+}
+
+// Command/packet transmitting functions
+
+static void event_command_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) {
+  if (hci_state < HCI_STARTED) {
+    LOG_ERROR("%s Returning, hci_layer not ready", __func__);
+    return;
+  }
+  if (command_credits > 0) {
+    waiting_command_t *wait_entry = fixed_queue_dequeue(queue);
+    command_credits--;
+
+    send_cmd_to_lower(wait_entry);
+  } else {
+    waiting_command_t *wait_entry = fixed_queue_dequeue(queue);
+    list_append(commands_pending_in_queue, wait_entry);
   }
 }
 
 static void event_packet_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) {
+  if (hci_state < HCI_STARTED) {
+    LOG_ERROR("%s Returning, hci_layer not ready", __func__);
+    return;
+  }
   // The queue may be the command queue or the packet queue, we don't care
   BT_HDR *packet = (BT_HDR *)fixed_queue_dequeue(queue);
 
@@ -539,8 +645,39 @@
     LOG_EVENT_INT(BT_HCI_TIMEOUT_TAG_NUM, wait_entry->opcode);
   }
 
-  LOG_ERROR(LOG_TAG, "%s restarting the bluetooth process.", __func__);
-  usleep(10000);
+  LOG_ERROR("%s restarting the bluetooth process.", __func__);
+  ssr_cleanup(0x22);//SSR reasno 0x22 = CMD TO
+
+  //Reset SOC status to trigger hciattach service
+  if (property_set("bluetooth.status", "off") < 0) {
+     LOG_ERROR(LOG_TAG, "hci_cmd_timeout: Error resetting SOC status\n ");
+  } else {
+     LOG_ERROR(LOG_TAG, "hci_cmd_timeout: SOC Status is reset\n ");
+  }
+
+  if (soc_type == BT_SOC_ROME || soc_type == BT_SOC_CHEROKEE) {
+    char value[PROPERTY_VALUE_MAX] = {0};
+    uint32_t hardware_error_timeout_ms = 2000;
+    bool enabled = false;
+#ifdef ENABLE_DBG_FLAGS
+    enabled = true;
+#endif
+    if (property_get("wc_transport.force_special_byte", value, NULL))
+      enabled = (strcmp(value, "false") == 0) ? false : true;
+    if (enabled) {
+      hardware_error_timer = alarm_new("hci.hardware_error_timer");
+      if (!hardware_error_timer) {
+        LOG_ERROR("%s unable to create hardware error timer.", __func__);
+        usleep(2000000);
+        kill(getpid(), SIGKILL);
+      }
+      if(soc_type == BT_SOC_CHEROKEE)
+        hardware_error_timeout_ms = 5000;
+      alarm_set(hardware_error_timer, hardware_error_timeout_ms, hardware_error_timer_expired, NULL);
+      return;
+    }
+  }
+  usleep(20000);
   kill(getpid(), SIGKILL);
 }
 
@@ -551,71 +688,100 @@
 static void hal_says_data_ready(serial_data_type_t type) {
   packet_receive_data_t *incoming = &incoming_packets[PACKET_TYPE_TO_INBOUND_INDEX(type)];
 
+  uint8_t reset;
+
   uint8_t byte;
   while (hal->read_data(type, &byte, 1) != 0) {
+    if (soc_type == BT_SOC_SMD) {
+        reset = hal->dev_in_reset();
+        if (reset) {
+            incoming = &incoming_packets[PACKET_TYPE_TO_INBOUND_INDEX(type = DATA_TYPE_EVENT)];
+            if(!create_hw_reset_evt_packet(incoming))
+                break;
+            else {
+            //Reset SOC status to trigger hciattach service
+                if(property_set("bluetooth.status", "off") < 0) {
+                    LOG_ERROR(LOG_TAG, "SSR: Error resetting SOC status\n ");
+                } else {
+                    ALOGE("SSR: SOC Status is reset\n ");
+                }
+            }
+        }
+    }
+
     switch (incoming->state) {
-      case BRAND_NEW:
-        // Initialize and prepare to jump to the preamble reading state
-        incoming->bytes_remaining = preamble_sizes[PACKET_TYPE_TO_INDEX(type)];
-        memset(incoming->preamble, 0, PREAMBLE_BUFFER_SIZE);
-        incoming->index = 0;
-        incoming->state = PREAMBLE;
-        // INTENTIONAL FALLTHROUGH
-      case PREAMBLE:
-        incoming->preamble[incoming->index] = byte;
-        incoming->index++;
-        incoming->bytes_remaining--;
+        case BRAND_NEW:
+            // Initialize and prepare to jump to the preamble reading state
+            incoming->bytes_remaining = preamble_sizes[PACKET_TYPE_TO_INDEX(type)];
+            memset(incoming->preamble, 0, PREAMBLE_BUFFER_SIZE);
+            incoming->index = 0;
+            incoming->state = PREAMBLE;
+            // INTENTIONAL FALLTHROUGH
+        case PREAMBLE:
+            incoming->preamble[incoming->index] = byte;
+            incoming->index++;
+            incoming->bytes_remaining--;
 
-        if (incoming->bytes_remaining == 0) {
-          // For event and sco preambles, the last byte we read is the length
-          incoming->bytes_remaining = (type == DATA_TYPE_ACL) ? RETRIEVE_ACL_LENGTH(incoming->preamble) : byte;
+            if (incoming->bytes_remaining == 0) {
+                // For event and sco preambles, the last byte we read is the length
+                incoming->bytes_remaining = (type == DATA_TYPE_ACL) ? RETRIEVE_ACL_LENGTH(incoming->preamble) : byte;
 
-          size_t buffer_size = BT_HDR_SIZE + incoming->index + incoming->bytes_remaining;
-          incoming->buffer = (BT_HDR *)buffer_allocator->alloc(buffer_size);
+                size_t buffer_size = BT_HDR_SIZE + incoming->index + incoming->bytes_remaining;
 
-          if (!incoming->buffer) {
-            LOG_ERROR(LOG_TAG, "%s error getting buffer for incoming packet of type %d and size %zd", __func__, type, buffer_size);
-            // Can't read any more of this current packet, so jump out
-            incoming->state = incoming->bytes_remaining == 0 ? BRAND_NEW : IGNORE;
+                if (buffer_size > MCA_USER_RX_BUF_SIZE) {
+                    LOG_ERROR(LOG_TAG, "%s buffer_size(%zu) exceeded allowed packet size, allocation not possible", __func__, buffer_size);
+                    incoming = &incoming_packets[PACKET_TYPE_TO_INBOUND_INDEX(type = DATA_TYPE_EVENT)];
+                    if(create_hw_reset_evt_packet(incoming))
+                        break;
+                    else
+                        return;
+                }
+
+                incoming->buffer = (BT_HDR *)buffer_allocator->alloc(buffer_size);
+
+                if (!incoming->buffer) {
+                    LOG_ERROR(LOG_TAG, "%s error getting buffer for incoming packet of type %d and size %zd", __func__, type, buffer_size);
+                    // Can't read any more of this current packet, so jump out
+                    incoming->state = incoming->bytes_remaining == 0 ? BRAND_NEW : IGNORE;
+                    break;
+                }
+
+                // Initialize the buffer
+                incoming->buffer->offset = 0;
+                incoming->buffer->layer_specific = 0;
+                incoming->buffer->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)];
+                memcpy(incoming->buffer->data, incoming->preamble, incoming->index);
+
+                incoming->state = incoming->bytes_remaining > 0 ? BODY : FINISHED;
+            }
+
             break;
-          }
+        case BODY:
+            incoming->buffer->data[incoming->index] = byte;
+            incoming->index++;
+            incoming->bytes_remaining--;
 
-          // Initialize the buffer
-          incoming->buffer->offset = 0;
-          incoming->buffer->layer_specific = 0;
-          incoming->buffer->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)];
-          memcpy(incoming->buffer->data, incoming->preamble, incoming->index);
+            size_t bytes_read = hal->read_data(type, (incoming->buffer->data + incoming->index), incoming->bytes_remaining);
+            incoming->index += bytes_read;
+            incoming->bytes_remaining -= bytes_read;
 
-          incoming->state = incoming->bytes_remaining > 0 ? BODY : FINISHED;
-        }
+            incoming->state = incoming->bytes_remaining == 0 ? FINISHED : incoming->state;
+            break;
+        case IGNORE:
+            incoming->bytes_remaining--;
+            if (incoming->bytes_remaining == 0) {
+                incoming->state = BRAND_NEW;
+                // Don't forget to let the hal know we finished the packet we were ignoring.
+                // Otherwise we'll get out of sync with hals that embed extra information
+                // in the uart stream (like H4). #badnewsbears
+                hal->packet_finished(type);
+                return;
+            }
 
-        break;
-      case BODY:
-        incoming->buffer->data[incoming->index] = byte;
-        incoming->index++;
-        incoming->bytes_remaining--;
-
-        size_t bytes_read = hal->read_data(type, (incoming->buffer->data + incoming->index), incoming->bytes_remaining);
-        incoming->index += bytes_read;
-        incoming->bytes_remaining -= bytes_read;
-
-        incoming->state = incoming->bytes_remaining == 0 ? FINISHED : incoming->state;
-        break;
-      case IGNORE:
-        incoming->bytes_remaining--;
-        if (incoming->bytes_remaining == 0) {
-          incoming->state = BRAND_NEW;
-          // Don't forget to let the hal know we finished the packet we were ignoring.
-          // Otherwise we'll get out of sync with hals that embed extra information
-          // in the uart stream (like H4). #badnewsbears
-          hal->packet_finished(type);
-          return;
-        }
-
-        break;
-      case FINISHED:
-        LOG_ERROR(LOG_TAG, "%s the state machine should not have been left in the finished state.", __func__);
-        break;
+            break;
+        case FINISHED:
+            LOG_ERROR(LOG_TAG, "%s the state machine should not have been left in the finished state.", __func__);
+            break;
     }
 
     if (incoming->state == FINISHED) {
@@ -623,18 +789,28 @@
       btsnoop->capture(incoming->buffer, true);
 
       if (type != DATA_TYPE_EVENT) {
-        packet_fragmenter->reassemble_and_dispatch(incoming->buffer);
+        if(hci_state == HCI_READY) {
+          packet_fragmenter->reassemble_and_dispatch(incoming->buffer);
+        } else {
+          LOG_WARN("%s, Ignoring the ACL pkt received", __func__);
+          buffer_allocator->free(incoming->buffer);
+        }
       } else if (!filter_incoming_event(incoming->buffer)) {
-        // Dispatch the event by event code
-        uint8_t *stream = incoming->buffer->data;
-        uint8_t event_code;
-        STREAM_TO_UINT8(event_code, stream);
+        if (hci_state == HCI_READY) {
+          // Dispatch the event by event code
+          uint8_t *stream = incoming->buffer->data;
+          uint8_t event_code;
+          STREAM_TO_UINT8(event_code, stream);
 
-        data_dispatcher_dispatch(
-          interface.event_dispatcher,
-          event_code,
-          incoming->buffer
-        );
+          data_dispatcher_dispatch(
+            interface.event_dispatcher,
+            event_code,
+            incoming->buffer
+          );
+        } else {
+          LOG_WARN("%s, Ignoring the event pkt received", __func__);
+          buffer_allocator->free(incoming->buffer);
+        }
       }
 
       // We don't control the buffer anymore
@@ -666,6 +842,10 @@
     STREAM_TO_UINT8(command_credits, stream);
     STREAM_TO_UINT16(opcode, stream);
 
+    if (HCI_RESET == opcode) {
+      hci_state = HCI_READY;
+    }
+
     wait_entry = get_waiting_command(opcode);
     if (!wait_entry) {
       // TODO: Currently command_credits aren't parsed at all; here or in higher layers...
@@ -689,9 +869,9 @@
     // If a command generates a command status event, it won't be getting a command complete event
 
     wait_entry = get_waiting_command(opcode);
-    if (!wait_entry)
+    if (!wait_entry) {
       LOG_WARN(LOG_TAG, "%s command status event with no matching command. opcode: 0x%x", __func__, opcode);
-    else if (wait_entry->status_callback)
+    } else if (wait_entry->status_callback)
       wait_entry->status_callback(status, wait_entry->command, wait_entry->context);
 
     goto intercepted;
@@ -716,9 +896,35 @@
     buffer_allocator->free(packet);
   }
 
+  if(command_credits > 0) {
+     const list_node_t *node = list_begin(commands_pending_in_queue);
+
+     if(node != list_end(commands_pending_in_queue)) {
+       waiting_command_t *wait_entry = list_node(node);
+       command_credits--;
+       list_remove(commands_pending_in_queue, wait_entry);
+       send_cmd_to_lower(wait_entry);
+    }
+  }
   return true;
 }
 
+/** SSR cleanup is used in HW reset cases
+** which would close all the client channels
+** and turns off the chip*/
+void ssr_cleanup (int reason) {
+   LOG_INFO("%s", __func__);
+   if (hci_state < HCI_STARTED) {
+     LOG_ERROR("%s Returning, hci_layer already shut down", __func__);
+     return;
+   }
+   if (vendor != NULL) {
+       vendor->ssr_cleanup(reason);
+   } else {
+       LOG_ERROR("%s: vendor is NULL", __func__);
+   }
+}
+
 // Callback for the fragmenter to dispatch up a completely reassembled packet
 static void dispatch_reassembled(BT_HDR *packet) {
   // Events should already have been dispatched before this point
@@ -765,6 +971,26 @@
     pthread_mutex_unlock(&commands_pending_response_lock);
     return wait_entry;
   }
+  // look for any command complete with improper VS Opcode
+  for (const list_node_t *node = list_begin(commands_pending_response);
+      node != list_end(commands_pending_response);
+      node = list_next(node)) {
+    waiting_command_t *wait_entry = list_node(node);
+
+    if (wait_entry && (wait_entry->opcode != opcode) &&
+        (((wait_entry->opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC) &&
+        ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC))) {
+        LOG_DEBUG("%s VS event found treat it as valid 0x%x", __func__, opcode);
+    }
+    else {
+        continue;
+    }
+
+    list_remove(commands_pending_response, wait_entry);
+
+    pthread_mutex_unlock(&commands_pending_response_lock);
+    return wait_entry;
+  }
 
   pthread_mutex_unlock(&commands_pending_response_lock);
   return NULL;
@@ -796,6 +1022,7 @@
     interface.transmit_command = transmit_command;
     interface.transmit_command_futured = transmit_command_futured;
     interface.transmit_downward = transmit_downward;
+    interface.ssr_cleanup = ssr_cleanup;
     interface_created = true;
   }
 }
@@ -815,6 +1042,23 @@
     interface_created = false;
   }
 }
+static bool create_hw_reset_evt_packet(packet_receive_data_t *incoming) {
+  uint8_t dev_ssr_event[3] = { 0x10, 0x01, 0x0A };
+  incoming->buffer = (BT_HDR *)buffer_allocator->alloc(BT_HDR_SIZE + 3);
+  if (incoming->buffer) {
+    LOG_ERROR(LOG_TAG, "sending H/w error event to stack\n ");
+    incoming->buffer->offset = 0;
+    incoming->buffer->layer_specific = 0;
+    incoming->buffer->event = MSG_HC_TO_STACK_HCI_EVT;
+    incoming->index = 3;
+    memcpy(incoming->buffer->data, &dev_ssr_event, 3);
+    incoming->state = FINISHED;
+    return true;
+  } else {
+    LOG_ERROR(LOG_TAG, "error getting buffer for H/W event\n ");
+    return false;
+  }
+}
 
 static const hci_hal_callbacks_t hal_callbacks = {
   hal_says_data_ready
diff --git a/hci/src/hci_packet_factory.c b/hci/src/hci_packet_factory.c
index 96f578a..1e95ee3 100644
--- a/hci/src/hci_packet_factory.c
+++ b/hci/src/hci_packet_factory.c
@@ -133,6 +133,10 @@
   return make_command_no_params(HCI_BLE_READ_RESOLVING_LIST_SIZE);
 }
 
+static BT_HDR *make_ble_read_adv_ext_size(void) {
+  return make_command_no_params(HCI_BLE_READ_NUM_ADV_SETS);
+}
+
 static BT_HDR *make_ble_read_suggested_default_data_length(void) {
     return make_command_no_params(HCI_BLE_READ_DEFAULT_DATA_LENGTH);
 }
@@ -141,6 +145,10 @@
     return make_command_no_params(HCI_READ_LOCAL_SUPPORTED_CODECS);
 }
 
+static BT_HDR *make_ble_read_offload_features_support(void) {
+    return make_command_no_params(HCI_BLE_VENDOR_CAP_OCF);
+}
+
 static BT_HDR *make_ble_set_event_mask(const bt_event_mask_t *event_mask) {
   uint8_t *stream;
   uint8_t parameter_size = sizeof(bt_event_mask_t);
@@ -196,9 +204,11 @@
   make_ble_read_supported_states,
   make_ble_read_local_supported_features,
   make_ble_read_resolving_list_size,
+  make_ble_read_adv_ext_size,
   make_ble_read_suggested_default_data_length,
   make_ble_set_event_mask,
-  make_read_local_supported_codecs
+  make_read_local_supported_codecs,
+  make_ble_read_offload_features_support
 };
 
 const hci_packet_factory_t *hci_packet_factory_get_interface() {
diff --git a/hci/src/hci_packet_parser.c b/hci/src/hci_packet_parser.c
index 9f7dae8..3209e1f 100644
--- a/hci/src/hci_packet_parser.c
+++ b/hci/src/hci_packet_parser.c
@@ -37,9 +37,10 @@
   size_t minimum_bytes_after);
 
 static void parse_generic_command_complete(BT_HDR *response) {
-  read_command_complete_header(response, NO_OPCODE_CHECKING, 0 /* bytes after */);
-
-  buffer_allocator->free(response);
+  if (response) {
+      read_command_complete_header(response, NO_OPCODE_CHECKING, 0 /* bytes after */);
+      buffer_allocator->free(response);
+  }
 }
 
 static void parse_read_buffer_size_response(
@@ -88,6 +89,21 @@
   buffer_allocator->free(response);
 }
 
+
+static void parse_ble_read_offload_features_response(
+    BT_HDR *response,
+    bool *ble_offload_features_supported) {
+
+  uint8_t *stream = read_command_complete_header(response, NO_OPCODE_CHECKING, 0 /* bytes after */);
+  if(stream) {
+    *ble_offload_features_supported  = true;
+  } else {
+    *ble_offload_features_supported  = false;
+  }
+
+  buffer_allocator->free(response);
+}
+
 static void parse_read_bd_addr_response(
     BT_HDR *response,
     bt_bdaddr_t *address_ptr) {
@@ -185,16 +201,29 @@
     uint8_t *resolving_list_size_ptr) {
 
   uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_RESOLVING_LIST_SIZE, 1 /* bytes after */);
+  assert(stream != NULL);
   STREAM_TO_UINT8(*resolving_list_size_ptr, stream);
 
   buffer_allocator->free(response);
 }
 
+static void parse_ble_read_adv_ext_size_response(
+    BT_HDR *response,
+    uint8_t *ble_adv_ext_size) {
+
+  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_NUM_ADV_SETS, 1 /* bytes after */);
+  assert(stream != NULL);
+  STREAM_TO_UINT8(*ble_adv_ext_size, stream);
+
+  buffer_allocator->free(response);
+}
+
 static void parse_ble_read_suggested_default_data_length_response(
     BT_HDR *response,
     uint16_t *ble_default_packet_length_ptr) {
 
   uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 2 /* bytes after */);
+  assert(stream != NULL);
   STREAM_TO_UINT8(*ble_default_packet_length_ptr, stream);
 
   buffer_allocator->free(response);
@@ -255,8 +284,10 @@
   parse_ble_read_supported_states_response,
   parse_ble_read_local_supported_features_response,
   parse_ble_read_resolving_list_size_response,
+  parse_ble_read_adv_ext_size_response,
   parse_ble_read_suggested_default_data_length_response,
-  parse_read_local_supported_codecs_response
+  parse_read_local_supported_codecs_response,
+  parse_ble_read_offload_features_response
 };
 
 const hci_packet_parser_t *hci_packet_parser_get_interface() {
diff --git a/hci/src/low_power_manager.c b/hci/src/low_power_manager.c
index f82a69f..3c5984a 100644
--- a/hci/src/low_power_manager.c
+++ b/hci/src/low_power_manager.c
@@ -1,4 +1,9 @@
 /******************************************************************************
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a contribution.
+ ******************************************************************************/
+/******************************************************************************
  *
  *  Copyright (C) 2014 Google, Inc.
  *
@@ -56,8 +61,8 @@
 static void event_idle_timeout(void *context);
 
 static void reset_state();
-static void start_idle_timer();
-static void stop_idle_timer();
+void start_idle_timer(bool check_LPM);
+void stop_idle_timer();
 
 static thread_fn event_functions[] = {
   event_disable,
@@ -124,7 +129,7 @@
   transmit_is_done = true;
   if (wake_state == LPM_WAKE_W4_TX_DONE || wake_state == LPM_WAKE_ASSERTED) {
     wake_state = LPM_WAKE_W4_TIMEOUT;
-    start_idle_timer();
+    start_idle_timer(true);
   }
 }
 
@@ -132,15 +137,17 @@
 
 static void enable(bool enable) {
   if (state == LPM_DISABLING) {
-    if (enable)
+    if (enable) {
       LOG_ERROR(LOG_TAG, "%s still processing prior disable request, cannot enable.", __func__);
-    else
+    } else {
       LOG_WARN(LOG_TAG, "%s still processing prior disable request, ignoring new request to disable.", __func__);
+    }
   } else if (state == LPM_ENABLING) {
-    if (enable)
+    if (enable) {
       LOG_ERROR(LOG_TAG, "%s still processing prior enable request, ignoring new request to enable.", __func__);
-    else
+    } else {
       LOG_WARN(LOG_TAG, "%s still processing prior enable request, cannot disable.", __func__);
+    }
   } else if (state == LPM_ENABLED && enable) {
     LOG_INFO(LOG_TAG, "%s already enabled.", __func__);
   } else if (state == LPM_DISABLED && !enable) {
@@ -158,7 +165,7 @@
   if (state == LPM_ENABLED && wake_state == LPM_WAKE_ASSERTED) {
     if (transmit_is_done) {
       wake_state = LPM_WAKE_W4_TIMEOUT;
-      start_idle_timer();
+      start_idle_timer(true);
     } else {
       wake_state = LPM_WAKE_W4_TX_DONE;
     }
@@ -185,18 +192,22 @@
     thread_post(thread, event_idle_timeout, NULL);
 }
 
-static void start_idle_timer() {
-  if (state == LPM_ENABLED) {
+void start_idle_timer(bool check_LPM) {
+  if (state == LPM_ENABLED || !check_LPM) {
     if (idle_timeout_ms == 0) {
        wake_deassert();
-    } else {
+    }
+    else {
        alarm_set(idle_alarm, idle_timeout_ms, idle_timer_expired, NULL);
     }
+
+    LOG_VERBOSE(LOG_TAG,"%s check_LPM = %d", __func__, check_LPM);
   }
 }
 
-static void stop_idle_timer() {
+void stop_idle_timer() {
   alarm_cancel(idle_alarm);
+  LOG_VERBOSE(LOG_TAG, "%s", __func__);
 }
 
 static void event_disable(UNUSED_ATTR void *context) {
@@ -235,7 +246,9 @@
   cleanup,
   post_command,
   wake_assert,
-  transmit_done
+  transmit_done,
+  start_idle_timer,
+  stop_idle_timer
 };
 
 const low_power_manager_t *low_power_manager_get_interface() {
diff --git a/hci/src/packet_fragmenter.c b/hci/src/packet_fragmenter.c
index eae6905..06fb972 100644
--- a/hci/src/packet_fragmenter.c
+++ b/hci/src/packet_fragmenter.c
@@ -153,6 +153,7 @@
       if (acl_length < L2CAP_HEADER_SIZE) {
         LOG_WARN(LOG_TAG, "%s L2CAP packet too small (%d < %d). Dropping it.", __func__, packet->len, L2CAP_HEADER_SIZE);
         buffer_allocator->free(packet);
+        GENERATE_VND_LOGS();
         return;
       }
 
@@ -164,6 +165,7 @@
           ((full_length + sizeof(BT_HDR)) > BT_DEFAULT_BUFFER_SIZE)) {
         LOG_ERROR(LOG_TAG, "%s L2CAP packet has invalid length (%d). Dropping it.", __func__, l2cap_length);
         buffer_allocator->free(packet);
+        GENERATE_VND_LOGS();
         return;
       }
 
@@ -194,6 +196,7 @@
       if (!partial_packet) {
         LOG_WARN(LOG_TAG, "%s got continuation for unknown packet. Dropping it.", __func__);
         buffer_allocator->free(packet);
+        GENERATE_VND_LOGS();
         return;
       }
 
diff --git a/hci/src/vendor.c b/hci/src/vendor.c
index c6bbd43..46ae0ac 100644
--- a/hci/src/vendor.c
+++ b/hci/src/vendor.c
@@ -90,6 +90,13 @@
   lib_interface = NULL;
   lib_handle = NULL;
 }
+void vendor_ssrcleanup(int reason) {
+  if (lib_interface)
+    lib_interface->ssr_cleanup(reason);
+  else
+    LOG_ERROR("%s lib_interface is NULL", __func__);
+
+}
 
 static int send_command(vendor_opcode_t opcode, void *param) {
   assert(lib_interface != NULL);
@@ -220,6 +227,7 @@
   send_command,
   send_async_command,
   set_callback,
+  vendor_ssrcleanup
 };
 
 const vendor_t *vendor_get_interface() {
diff --git a/include/bt_logger_lib.h b/include/bt_logger_lib.h
new file mode 100644
index 0000000..30467af
--- /dev/null
+++ b/include/bt_logger_lib.h
@@ -0,0 +1,78 @@
+/*********************************************************************
+*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*   * Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   * Redistributions in binary form must reproduce the above
+*     copyright notice, this list of conditions and the following
+*     disclaimer in the documentation and/or other materials provided
+*     with the distribution.
+*   * Neither the name of The Linux Foundation nor the names of its
+*     contributors may be used to endorse or promote products derived
+*     from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+************************************************************************/
+
+#include <stdio.h>
+#include <sys/types.h>
+
+/**
+ * Commands
+ */
+typedef enum  {
+    VENDOR_LOGGER_LOGS = 201, // Signifies Packet containing Logger Log
+    GENERATE_VND_LOG_SIGNAL, // Signifies command to generate logs
+    START_SNOOP_SIGNAL,
+    STOP_SNOOP_SIGNAL,
+    STOP_LOGGING_SIGNAL,
+} CommandTypes;
+
+void init_vnd_Logger(void);
+void clean_vnd_logger(void);
+
+typedef struct {
+    /** Set to sizeof(bt_vndor_interface_t) */
+    size_t          size;
+
+    /*
+     * Functions need to be implemented in Logger libray (libbt-logClient.so).
+     */
+
+    /*
+     *  Initialize logging by conneting client socket
+     *  to Logger process
+     */
+    int   (*init)(void);
+
+    /**  Sending Logs of Logger process */
+    void (*send_log_msg)(const char *tag, const char *fmt_str, va_list ap);
+    void (*send_log_data)(const char *tag, const char *fmt_str, ...);
+
+    /**  Sending Logs of Logger process */
+    void (*send_event)(char evt);
+
+    /** Closes the socket connection to logger process */
+    int  (*cleanup)(void);
+
+} bt_logger_interface_t;
+
+#define GENERATE_VND_LOGS() if(logger_interface)logger_interface->send_event(GENERATE_VND_LOG_SIGNAL)
+#define START_SNOOP_LOGGING() if(logger_interface)logger_interface->send_event(START_SNOOP_SIGNAL)
+#define STOP_SNOOP_LOGGING() if(logger_interface)logger_interface->send_event(STOP_SNOOP_SIGNAL)
diff --git a/include/bt_target.h b/include/bt_target.h
index 184a6cd..37ef9ae 100644
--- a/include/bt_target.h
+++ b/include/bt_target.h
@@ -1,3 +1,9 @@
+ /******************************************************************************
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a contribution.
+ ******************************************************************************/
+
 /******************************************************************************
  *
  *  Copyright (c) 2014 The Android Open Source Project
@@ -42,6 +48,11 @@
 #define L2CAP_EXTFEA_SUPPORTED_MASK (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE | L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_FIXED_CHNLS)
 #endif
 
+/* This feature is used to update any QCOM related changes in the stack*/
+#ifndef BLUETOOTH_QTI_SW
+#define BLUETOOTH_QTI_SW TRUE
+#endif
+
 #ifndef BTUI_OPS_FORMATS
 #define BTUI_OPS_FORMATS (BTA_OP_VCARD21_MASK | BTA_OP_ANY_MASK)
 #endif
@@ -87,7 +98,7 @@
 #endif
 
 #ifndef BTA_AV_SINK_INCLUDED
-#define BTA_AV_SINK_INCLUDED FALSE
+#define BTA_AV_SINK_INCLUDED TRUE
 #endif
 
 #ifndef BTA_DISABLE_DELAY
@@ -127,7 +138,7 @@
 #endif
 
 #ifndef BTIF_A2DP_SRC_BIT_DEPTH
-#define BTIF_A2DP_SRC_BIT_DEPTH 16
+#define BTIF_A2DP_SRC_BIT_DEPTH 32
 #endif
 
 #ifndef BTIF_A2DP_SRC_NUM_CHANNELS
@@ -143,6 +154,15 @@
 #define BT_USE_TRACES  TRUE
 #endif
 
+#ifndef BT_TRACE_BTIF
+#define BT_TRACE_BTIF  TRUE
+#endif
+
+
+#ifndef BT_TRACE_LATENCY_AUDIO
+#define BT_TRACE_LATENCY_AUDIO  TRUE
+#endif
+
 #ifndef BT_TRACE_VERBOSE
 #define BT_TRACE_VERBOSE  FALSE
 #endif
@@ -155,6 +175,11 @@
 #define HL_INCLUDED  TRUE
 #endif
 
+#ifndef AAC_ENCODER_INCLUDED
+#define AAC_ENCODER_INCLUDED   TRUE
+#endif
+
+
 #ifndef AG_VOICE_SETTINGS
 #define AG_VOICE_SETTINGS  HCI_DEFAULT_VOICE_SETTINGS
 #endif
@@ -171,6 +196,15 @@
 
 //------------------End added from bdroid_buildcfg.h---------------------
 
+/******************************************************************************
+**
+** Test Application interface
+**
+******************************************************************************/
+
+#ifndef TEST_APP_INTERFACE
+#define TEST_APP_INTERFACE           TRUE
+#endif
 
 /******************************************************************************
 **
@@ -330,10 +364,15 @@
 #define BTM_SCO_HCI_INCLUDED    FALSE   /* TRUE includes SCO over HCI code */
 #endif
 
+#if (BLUETOOTH_QTI_SW == TRUE) /* Enable WBS only under this flag.*/
+#define BTM_WBS_INCLUDED            TRUE
+#else
 /* Includes WBS if TRUE */
 #ifndef BTM_WBS_INCLUDED
 #define BTM_WBS_INCLUDED        FALSE   /* TRUE includes WBS code */
 #endif
+#endif
+
 
 /*  This is used to work around a controller bug that doesn't like Disconnect
 **  issued while there is a role switch in progress
@@ -477,6 +516,11 @@
 #define BTM_MAX_VSE_CALLBACKS           3
 #endif
 
+/* Safe reattempt even after device is blacklisted for role switch */
+#ifndef BTM_SAFE_REATTEMPT_ROLE_SWITCH
+#define BTM_SAFE_REATTEMPT_ROLE_SWITCH TRUE
+#endif
+
 /******************************************
 **    Lisbon Features
 *******************************************/
@@ -531,21 +575,21 @@
 **
 ******************************************************************************/
 
-/* The maximum number of simultaneous links that L2CAP can support. */
-#ifndef MAX_ACL_CONNECTIONS
-#define MAX_L2CAP_LINKS             7
-#else
-#define MAX_L2CAP_LINKS             MAX_ACL_CONNECTIONS
-#endif
-
 /* The maximum number of simultaneous channels that L2CAP can support. */
 #ifndef MAX_L2CAP_CHANNELS
-#define MAX_L2CAP_CHANNELS          16
+#define MAX_L2CAP_CHANNELS          20
+#endif
+
+/* The maximum number of simultaneous links that L2CAP can support. */
+#ifndef MAX_L2CAP_CHANNELS
+#define MAX_L2CAP_LINKS             7
+#else
+#define MAX_L2CAP_LINKS             MAX_L2CAP_CHANNELS
 #endif
 
 /* The maximum number of simultaneous applications that can register with L2CAP. */
 #ifndef MAX_L2CAP_CLIENTS
-#define MAX_L2CAP_CLIENTS           15
+#define MAX_L2CAP_CLIENTS           19
 #endif
 
 /* The number of seconds of link inactivity before a link is disconnected. */
@@ -588,7 +632,7 @@
 
 /* Whether link wants to be the master or the slave. */
 #ifndef L2CAP_DESIRED_LINK_ROLE
-#define L2CAP_DESIRED_LINK_ROLE     HCI_ROLE_SLAVE
+#define L2CAP_DESIRED_LINK_ROLE     HCI_ROLE_MASTER
 #endif
 
 /* Include Non-Flushable Packet Boundary Flag feature of Lisbon */
@@ -665,6 +709,11 @@
 #endif
 
 
+
+#ifndef HCI_RAW_CMD_INCLUDED
+#define HCI_RAW_CMD_INCLUDED    TRUE
+#endif
+
 /******************************************************************************
 **
 ** BLE
@@ -675,6 +724,14 @@
 #define BLE_INCLUDED            TRUE
 #endif
 
+/*LE_L2CAP_CODE*/
+/*LE Credit Based Flow Control Mode*/
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+#ifndef LE_L2CAP_CFC_INCLUDED
+#define LE_L2CAP_CFC_INCLUDED        TRUE
+#endif  /*LE_L2CAP_CFC_INCLUDED */
+#endif /* BLE_INCLUDED */
+
 #ifndef BLE_ANDROID_CONTROLLER_SCAN_FILTER
 #define BLE_ANDROID_CONTROLLER_SCAN_FILTER            TRUE
 #endif
@@ -691,6 +748,10 @@
 #define BLE_PRIVACY_SPT         TRUE
 #endif
 
+#ifndef BLE_EXTENDED_ADV_SUPPORT
+#define BLE_EXTENDED_ADV_SUPPORT TRUE
+#endif
+
 /*
  * Enables or disables support for local privacy (ex. address rotation)
  */
@@ -715,6 +776,11 @@
 #define BLE_MAX_L2CAP_CLIENTS           15
 #endif
 
+#ifndef BLE_HH_QUALIFICATION_ENABLED
+#define BLE_HH_QUALIFICATION_ENABLED        FALSE
+#endif
+
+
 /******************************************************************************
 **
 ** ATT/GATT Protocol/Profile Settings
@@ -771,7 +837,11 @@
 #endif
 
 #ifndef GATT_MAX_PHY_CHANNEL
+#ifndef MAX_L2CAP_CHANNELS
 #define GATT_MAX_PHY_CHANNEL        7
+#else
+#define GATT_MAX_PHY_CHANNEL        MAX_L2CAP_CHANNELS
+#endif
 #endif
 
 /* Used for conformance testing ONLY */
@@ -1156,9 +1226,15 @@
 #define AVDT_NUM_LINKS              2
 #endif
 
-/* Number of simultaneous stream endpoints. */
+/* Number of simultaneous stream endpoints.
+ * Audio*2 + Video*2 + 1 Additional
+ */
 #ifndef AVDT_NUM_SEPS
-#define AVDT_NUM_SEPS               3
+#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE)
+#define AVDT_NUM_SEPS               9
+#else
+#define AVDT_NUM_SEPS               7
+#endif
 #endif
 
 /* Number of transport channels setup by AVDT for all media streams */
@@ -1168,7 +1244,7 @@
 
 /* Maximum size in bytes of the codec capabilities information element. */
 #ifndef AVDT_CODEC_SIZE
-#define AVDT_CODEC_SIZE             10
+#define AVDT_CODEC_SIZE             20
 #endif
 
 /* Maximum size in bytes of the content protection information element. */
@@ -1333,7 +1409,11 @@
 #endif
 
 #ifndef HID_HOST_MAX_DEVICES
+#ifndef MAX_L2CAP_CHANNELS
 #define HID_HOST_MAX_DEVICES        7
+#else
+#define HID_HOST_MAX_DEVICES        MAX_L2CAP_CHANNELS
+#endif
 #endif
 
 #ifndef HID_HOST_MTU
@@ -1359,6 +1439,10 @@
 #define A2D_INCLUDED            TRUE
 #endif
 
+#ifndef A2D_M24_INCLUDED
+#define A2D_M24_INCLUDED    A2D_INCLUDED
+#endif
+
 /******************************************************************************
 **
 ** AVCTP
@@ -1370,9 +1454,36 @@
 #define AVCT_NUM_LINKS              2
 #endif
 
-/* Number of simultaneous AVCTP connections. */
+/* Number of simultaneous AVCTP connections.
+ * Audio*2 + Video*2 + 1 Additional */
 #ifndef AVCT_NUM_CONN
-#define AVCT_NUM_CONN               3
+#define AVCT_NUM_CONN               5
+#endif
+
+/* Buffer size to reassemble the SDU. */
+#ifndef AVCT_BR_USER_RX_BUF_SIZE
+#define AVCT_BR_USER_RX_BUF_SIZE    BT_DEFAULT_BUFFER_SIZE
+#endif
+
+/* Buffer size to hold the SDU. */
+#ifndef AVCT_BR_USER_TX_BUF_SIZE
+#define AVCT_BR_USER_TX_BUF_SIZE    BT_DEFAULT_BUFFER_SIZE
+#endif
+
+/*
+ * Buffer size used to hold MPS segments during SDU reassembly
+ */
+#ifndef AVCT_BR_FCR_RX_BUF_SIZE
+#define AVCT_BR_FCR_RX_BUF_SIZE     BT_DEFAULT_BUFFER_SIZE
+#endif
+
+/*
+ * Default buffer size used to hold MPS segments used in (re)transmissions.
+ * The size of each buffer must be able to hold the maximum MPS segment size
+ * passed in tL2CAP_FCR_OPTIONS plus BT_HDR (8) + HCI preamble (4) +
+ * L2CAP_MIN_OFFSET (11 - as of BT 2.1 + EDR Spec).+1452 */
+#ifndef AVCT_BR_FCR_TX_BUF_SIZE
+#define AVCT_BR_FCR_TX_BUF_SIZE     BT_DEFAULT_BUFFER_SIZE
 #endif
 
 /******************************************************************************
@@ -1393,6 +1504,30 @@
 #define AVRC_CTLR_INCLUDED          TRUE
 #endif
 
+#ifndef SDP_AVRCP_1_6
+#define SDP_AVRCP_1_6               TRUE
+#endif
+
+#ifndef  SDP_AVRCP_1_5
+#define SDP_AVRCP_1_5               FALSE
+#endif
+
+#if (defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE))
+#ifndef AVCT_COVER_ART_INCLUDED
+#define AVCT_COVER_ART_INCLUDED     TRUE
+#endif
+#endif
+
+#if ((defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE)) || \
+        (defined(SDP_AVRCP_1_5) && (SDP_AVRCP_1_5 == TRUE)))
+#ifndef AVCT_BROWSE_INCLUDED
+#define AVCT_BROWSE_INCLUDED        TRUE
+#else
+#ifndef AVCT_BROWSE_INCLUDED
+#define AVCT_BROWSE_INCLUDED        FALSE
+#endif
+#endif
+#endif
 /******************************************************************************
 **
 ** MCAP
@@ -1407,6 +1542,7 @@
 #define MCA_CTRL_MTU    60
 #endif
 
+
 /* The maximum number of registered MCAP instances. */
 #ifndef MCA_NUM_REGS
 #define MCA_NUM_REGS    12
@@ -1499,6 +1635,11 @@
 #define MCA_FCR_OPT_MPS_SIZE            1000
 #endif
 
+/* Enable this flag if require ,default value is false */
+#ifndef MCA_DELAY_DELETE_MDL_RSP
+#define MCA_DELAY_DELETE_MDL_RSP FALSE
+#endif
+
 /******************************************************************************
 **
 ** Sleep Mode (Low Power Mode)
diff --git a/include/bt_testapp.h b/include/bt_testapp.h
new file mode 100644
index 0000000..421b3fd
--- /dev/null
+++ b/include/bt_testapp.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *        * Redistributions of source code must retain the above copyright
+ *          notice, this list of conditions and the following disclaimer.
+ *        * Redistributions in binary form must reproduce the above copyright
+ *            notice, this list of conditions and the following disclaimer in the
+ *            documentation and/or other materials provided with the distribution.
+ *        * Neither the name of The Linux Foundation nor
+ *            the names of its contributors may be used to endorse or promote
+ *            products derived from this software without specific prior written
+ *            permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.    IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef TEST_APP_INTERFACE
+#ifndef ANDROID_INCLUDE_BT_TESTAPP_H
+#define ANDROID_INCLUDE_BT_TESTAPP_H
+#include <stdio.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/prctl.h>
+#include <linux/capability.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <private/android_filesystem_config.h>
+#include <android/log.h>
+#include <hardware/bluetooth.h>
+#include "l2c_api.h"
+#include "sdp_api.h"
+#include "gatt_api.h"
+#include "gap_api.h"
+#include "mca_api.h"
+#include <hardware/hardware.h>
+#include "btm_api.h"
+
+__BEGIN_DECLS
+
+typedef void (tREMOTE_DEVICE_NAME_CB) (void *p1);
+
+enum {
+    SUCCESS,
+    FAIL
+};
+
+typedef enum {
+    DUMMY,
+    ALL,
+    SPP,
+    FTP,
+    OPP,
+    MAP,
+    PBAP,
+    DUN,
+    NOT_SUPPORTED,
+}profileName;
+typedef enum {
+    TEST_APP_L2CAP,
+    TEST_APP_RFCOMM,
+    TEST_APP_MCAP,
+    TEST_APP_GATT,
+    TEST_APP_GAP,
+    TEST_APP_SMP
+} test_app_profile;
+typedef struct {
+
+    /** set to sizeof(Btl2capInterface) */
+    size_t          size;
+    /** Register the L2cap callbacks  */
+    bt_status_t (*Init)(tL2CAP_APPL_INFO* callbacks);
+    bt_status_t (*RegisterPsm)(UINT16 psm, BOOLEAN conn_type, UINT16 sec_level);
+    bt_status_t (*Deregister)(UINT16 psm);
+    UINT16      (*AllocatePsm)(void);
+    UINT16      (*Connect)(UINT16 psm, bt_bdaddr_t *bd_addr);
+    BOOLEAN     (*ConnectRsp)(BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid, UINT16 result, UINT16 status);
+    UINT16      (*ErtmConnectReq)(UINT16 psm, BD_ADDR p_bd_addr, tL2CAP_ERTM_INFO *p_ertm_info);
+    BOOLEAN     (*ErtmConnectRsp)(BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid,
+                                             UINT16 result, UINT16 status,
+                                             tL2CAP_ERTM_INFO *p_ertm_info);
+    BOOLEAN     (*ConfigReq)(UINT16 cid, tL2CAP_CFG_INFO *p_cfg);
+    BOOLEAN     (*ConfigRsp)(UINT16 cid, tL2CAP_CFG_INFO *p_cfg);
+    BOOLEAN     (*DisconnectReq)(UINT16 cid);
+    BOOLEAN     (*DisconnectRsp)(UINT16 cid);
+    UINT8       (*DataWrite)(UINT16 cid, char *p_data, UINT32 len);
+    BOOLEAN     (*Ping)(BD_ADDR p_bd_addr, tL2CA_ECHO_RSP_CB *p_cb);
+    BOOLEAN     (*Echo)(BD_ADDR p_bd_addr, BT_HDR *p_data, tL2CA_ECHO_DATA_CB *p_callback);
+    BOOLEAN     (*SetIdleTimeout)(UINT16 cid, UINT16 timeout, BOOLEAN is_global);
+    BOOLEAN     (*SetIdleTimeoutByBdAddr)(BD_ADDR bd_addr, UINT16 timeout);
+    UINT8       (*SetDesireRole)(UINT8 new_role);
+	void        (*SetSecConnOnlyMode)(BOOLEAN secvalue);
+    UINT16      (*LocalLoopbackReq)(UINT16 psm, UINT16 handle, BD_ADDR p_bd_addr);
+    UINT16      (*FlushChannel)(UINT16 lcid, UINT16 num_to_flush);
+    BOOLEAN     (*SetAclPriority)(BD_ADDR bd_addr, UINT8 priority);
+    BOOLEAN     (*FlowControl)(UINT16 cid, BOOLEAN data_enabled);
+    BOOLEAN     (*SendTestSFrame)(UINT16 cid, BOOLEAN rr_or_rej, UINT8 back_track);
+    BOOLEAN     (*SetTxPriority)(UINT16 cid, tL2CAP_CHNL_PRIORITY priority);
+    BOOLEAN     (*RegForNoCPEvt)(tL2CA_NOCP_CB *p_cb, BD_ADDR p_bda);
+    BOOLEAN     (*SetChnlDataRate)(UINT16 cid, tL2CAP_CHNL_DATA_RATE tx, tL2CAP_CHNL_DATA_RATE rx);
+    BOOLEAN     (*SetFlushTimeout)(BD_ADDR bd_addr, UINT16 flush_tout);
+    UINT8       (*DataWriteEx)(UINT16 cid, BT_HDR *p_data, UINT16 flags);
+    BOOLEAN     (*SetChnlFlushability)(UINT16 cid, BOOLEAN is_flushable);
+    BOOLEAN     (*GetPeerFeatures)(BD_ADDR bd_addr, UINT32 *p_ext_feat, UINT8 *p_chnl_mask);
+    BOOLEAN     (*GetBDAddrbyHandle)(UINT16 handle, BD_ADDR bd_addr);
+    UINT8       (*GetChnlFcrMode)(UINT16 lcid);
+    UINT16      (*SendFixedChnlData)(UINT16 fixed_cid, BD_ADDR rem_bda, BT_HDR *p_buf);
+    void  (*Cleanup)(void);
+    bt_status_t (*RegisterLePsm) (UINT16 le_psm, BOOLEAN ConnType, UINT16 SecLevel,
+                                    UINT8 enc_key_size);
+    bt_status_t (*LeDeregister)(UINT16 psm);
+    UINT16 (*LeConnect) (UINT16 le_psm , BD_ADDR address, tL2CAP_LE_CFG_INFO *p_cfg);
+    BOOLEAN (*LeConnectRsp) (BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid, UINT16 result,
+                             UINT16 status, tL2CAP_LE_CFG_INFO *p_cfg);
+    BOOLEAN (*LeFlowControl) (UINT16 lcid, UINT16 credits);
+    void (*LeFreeBuf)(BT_HDR *p_buf);
+} btl2cap_interface_t;
+
+typedef struct
+{
+    size_t    size;
+    void (*Init)(void);
+    tMCA_HANDLE (*Register)(tMCA_REG *p_reg, tMCA_CTRL_CBACK *p_cback);
+    void        (*Deregister)(tMCA_HANDLE handle);
+    tMCA_RESULT (*CreateDep)(tMCA_HANDLE handle, tMCA_DEP *p_dep, tMCA_CS *p_cs);
+    tMCA_RESULT (*DeleteDep)(tMCA_HANDLE handle, tMCA_DEP dep);
+    tMCA_RESULT (*ConnectReq)(tMCA_HANDLE handle, BD_ADDR bd_addr,
+                                          UINT16 ctrl_psm,
+                                          UINT16 sec_mask);
+    tMCA_RESULT (*DisconnectReq)(tMCA_CL mcl);
+    tMCA_RESULT (*CreateMdl)(tMCA_CL mcl, tMCA_DEP dep, UINT16 data_psm,
+                                         UINT16 mdl_id, UINT8 peer_dep_id,
+                                         UINT8 cfg, const tMCA_CHNL_CFG *p_chnl_cfg);
+    tMCA_RESULT (*CreateMdlRsp)(tMCA_CL mcl, tMCA_DEP dep,
+                                            UINT16 mdl_id, UINT8 cfg, UINT8 rsp_code,
+                                            const tMCA_CHNL_CFG *p_chnl_cfg);
+    tMCA_RESULT (*CloseReq)(tMCA_DL mdl);
+    tMCA_RESULT (*ReconnectMdl)(tMCA_CL mcl, tMCA_DEP dep, UINT16 data_psm,
+                                            UINT16 mdl_id, const tMCA_CHNL_CFG *p_chnl_cfg);
+    tMCA_RESULT (*ReconnectMdlRsp)(tMCA_CL mcl, tMCA_DEP dep,
+                                               UINT16 mdl_id, UINT8 rsp_code,
+                                               const tMCA_CHNL_CFG *p_chnl_cfg);
+    tMCA_RESULT (*DataChnlCfg)(tMCA_CL mcl, const tMCA_CHNL_CFG *p_chnl_cfg);
+    tMCA_RESULT (*Abort)(tMCA_CL mcl);
+    tMCA_RESULT (*Delete)(tMCA_CL mcl, UINT16 mdl_id);
+    tMCA_RESULT (*WriteReq)(tMCA_DL mdl, BT_HDR *p_pkt);
+    UINT16 (*GetL2CapChannel) (tMCA_DL mdl);
+}btmcap_interface_t;
+
+typedef struct
+{
+    size_t    size;
+    //GATT common APIs (Both client and server)
+    tGATT_IF (*Register) (tBT_UUID *p_app_uuid128, tGATT_CBACK *p_cb_info);
+    void (*Deregister) (tGATT_IF gatt_if);
+    void (*StartIf) (tGATT_IF gatt_if);
+    BOOLEAN (*Connect) (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct,tBT_TRANSPORT transport);
+    tGATT_STATUS (*Disconnect) (UINT16 conn_id);
+    BOOLEAN (*Listen) (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr);
+
+    //GATT Client APIs
+    tGATT_STATUS (*cConfigureMTU) (UINT16 conn_id, UINT16  mtu);
+    tGATT_STATUS (*cDiscover) (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_PARAM *p_param );
+    tGATT_STATUS (*cRead) (UINT16 conn_id, tGATT_READ_TYPE type, tGATT_READ_PARAM *p_read);
+    tGATT_STATUS (*cWrite) (UINT16 conn_id, tGATT_WRITE_TYPE type, tGATT_VALUE *p_write);
+    tGATT_STATUS (*cExecuteWrite) (UINT16 conn_id, BOOLEAN is_execute);
+    tGATT_STATUS (*cSendHandleValueConfirm) (UINT16 conn_id, UINT16 handle);
+    void (*cSetIdleTimeout)(BD_ADDR bd_addr, UINT16 idle_tout);
+    void (*cSetVisibility) (UINT16 disc_mode, UINT16 conn_mode);
+
+    //GATT Server APIs
+    //TODO - Add api on the need basis
+
+}btgatt_test_interface_t;
+
+typedef struct
+{
+    size_t    size;
+    void (*init)(void);
+    BOOLEAN (*Register) (tSMP_CALLBACK *p_cback);
+    tSMP_STATUS (*Pair) (BD_ADDR bd_addr);
+    BOOLEAN (*PairCancel) (BD_ADDR bd_addr);
+    void (*SecurityGrant)(BD_ADDR bd_addr, UINT8 res);
+    void (*PasskeyReply) (BD_ADDR bd_addr, UINT8 res, UINT32 passkey);
+    BOOLEAN (*Encrypt) (UINT8 *key, UINT8 key_len, UINT8 *plain_text, UINT8 pt_len, tSMP_ENC *p_out);
+}btsmp_interface_t;
+typedef struct
+{
+    size_t    size;
+    void (*Gap_AttrInit)();
+    void (*Gap_BleAttrDBUpdate)(BD_ADDR bd_addr, UINT16 int_min, UINT16 int_max, UINT16 latency, UINT16 sp_tout);
+}btgap_interface_t;
+
+/** Bluetooth RFC tool commands */
+typedef enum {
+    RFC_TEST_CLIENT =1,
+    RFC_TEST_FRAME_ERROR,
+    RFC_TEST_ROLE_SWITCH,
+    RFC_TEST_SERVER,
+    RFC_TEST_DISCON,
+    RFC_TEST_CLIENT_TEST_MSC_DATA, //For PTS test case BV 21 and 22
+    RFC_TEST_WRITE_DATA
+}rfc_test_cmd_t;
+
+
+typedef struct {
+    bt_bdaddr_t bdadd;
+    uint8_t     scn; //Server Channel Number
+}bt_rfc_conn_t;
+
+typedef struct {
+    bt_bdaddr_t bdadd;
+    uint8_t     role; //0x01 for master
+}bt_role_sw;
+
+typedef union {
+    bt_rfc_conn_t  conn;
+    uint8_t        server;
+    bt_role_sw     role_switch;
+}tRfcomm_test;
+
+typedef struct {
+    rfc_test_cmd_t param;
+    tRfcomm_test   data;
+}tRFC;
+
+typedef struct {
+    size_t          size;
+    bt_status_t (*init)( tL2CAP_APPL_INFO* callbacks );
+    void  (*rdut_rfcomm)( UINT8 server );
+    void  (*rdut_rfcomm_test_interface)( tRFC *input);
+    bt_status_t (*connect)( bt_bdaddr_t *bd_addr );
+    void  (*cleanup)( void );
+} btrfcomm_interface_t;
+
+#endif
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_TESTAPP_H */
diff --git a/include/bt_trace.h b/include/bt_trace.h
index fea0c3c..744c63d 100644
--- a/include/bt_trace.h
+++ b/include/bt_trace.h
@@ -112,7 +112,8 @@
 
 /* LayerIDs for BT APP */
 #define BTTRC_ID_BTAPP                     87
-#define BTTRC_ID_BT_PROTOCOL               88         /* this is a temporary solution to allow dynamic
+#define BTTRC_ID_LATENCY_AUDIO             88
+#define BTTRC_ID_BT_PROTOCOL               89         /* this is a temporary solution to allow dynamic
                                                          enable/disable of BT_PROTOCOL_TRACE */
 #define BTTRC_ID_MAX_ID                    BTTRC_ID_BT_PROTOCOL
 #define BTTRC_ID_ALL_LAYERS                0xFF       /* all trace layers */
@@ -120,6 +121,7 @@
 #define BTTRC_PARAM_UINT8                  1
 #define BTTRC_PARAM_UINT16                 2
 #define BTTRC_PARAM_UINT32                 3
+extern void BTA_setStackLog( const char* log_layer, int log_level);
 
 /* Enables or disables verbose trace information. */
 #ifndef BT_TRACE_VERBOSE
@@ -220,150 +222,158 @@
 #define BT_TRACE(l,t,...)                        LogMsg((TRACE_CTRL_GENERAL | (l) | TRACE_ORG_STACK | (t)), ##__VA_ARGS__)
 #define BT_ERROR_TRACE(l,...)                    LogMsg(TRACE_CTRL_GENERAL | (l) | TRACE_ORG_STACK | TRACE_TYPE_ERROR, ##__VA_ARGS__)
 
+#define VND_TRACE(l,t,...)                        vnd_LogMsg((TRACE_CTRL_GENERAL | (l) | TRACE_ORG_STACK | (t)), ##__VA_ARGS__)
+#define GENERATE_VENDOR_LOGS() vnd_GenerateLogs()
+
 /* Define tracing for the HCI unit
 */
 
-#define HCI_TRACE_ERROR(...)                     {if (btu_trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_HCI, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define HCI_TRACE_WARNING(...)                   {if (btu_trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_HCI, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define HCI_TRACE_EVENT(...)                     {if (btu_trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_HCI, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define HCI_TRACE_DEBUG(...)                     {if (btu_trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_HCI, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define HCI_TRACE_ERROR(...)                     {if (btu_trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_HCI, TRACE_TYPE_ERROR, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_HCI, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define HCI_TRACE_WARNING(...)                   {if (btu_trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_HCI, TRACE_TYPE_WARNING, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_HCI, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define HCI_TRACE_EVENT(...)                     {if (btu_trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_HCI, TRACE_TYPE_EVENT, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_HCI, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define HCI_TRACE_DEBUG(...)                     {if (btu_trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_HCI, TRACE_TYPE_DEBUG, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_HCI, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
 
 
 /* Define tracing for BTM
 */
-#define BTM_TRACE_ERROR(...)                     {if (btm_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_BTM, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define BTM_TRACE_WARNING(...)                   {if (btm_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_BTM, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define BTM_TRACE_API(...)                       {if (btm_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_BTM, TRACE_TYPE_API, ##__VA_ARGS__);}
-#define BTM_TRACE_EVENT(...)                     {if (btm_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_BTM, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define BTM_TRACE_DEBUG(...)                     {if (btm_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_BTM, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define BTM_TRACE_ERROR(...)                     {if (btm_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_BTM, TRACE_TYPE_ERROR, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_BTM, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define BTM_TRACE_WARNING(...)                   {if (btm_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_BTM, TRACE_TYPE_WARNING, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_BTM, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define BTM_TRACE_API(...)                       {if (btm_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_BTM, TRACE_TYPE_API, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_BTM, TRACE_TYPE_API, ##__VA_ARGS__);}
+#define BTM_TRACE_EVENT(...)                     {if (btm_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_BTM, TRACE_TYPE_EVENT, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_BTM, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define BTM_TRACE_DEBUG(...)                     {if (btm_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_BTM, TRACE_TYPE_DEBUG, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_BTM, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
 
 
 /* Define tracing for the L2CAP unit
 */
-#define L2CAP_TRACE_ERROR(...)                   {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_L2CAP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define L2CAP_TRACE_WARNING(...)                 {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_L2CAP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define L2CAP_TRACE_API(...)                     {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_L2CAP, TRACE_TYPE_API, ##__VA_ARGS__);}
-#define L2CAP_TRACE_EVENT(...)                   {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_L2CAP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define L2CAP_TRACE_DEBUG(...)                   {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_L2CAP, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define L2CAP_TRACE_ERROR(...)                   {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_L2CAP, TRACE_TYPE_ERROR, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_L2CAP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define L2CAP_TRACE_WARNING(...)                 {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_L2CAP, TRACE_TYPE_WARNING, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_L2CAP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define L2CAP_TRACE_API(...)                     {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_L2CAP, TRACE_TYPE_API, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_L2CAP, TRACE_TYPE_API, ##__VA_ARGS__);}
+#define L2CAP_TRACE_EVENT(...)                   {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_L2CAP, TRACE_TYPE_EVENT, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_L2CAP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define L2CAP_TRACE_DEBUG(...)                   {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_L2CAP, TRACE_TYPE_DEBUG, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_L2CAP, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
 
 /* Define tracing for the SDP unit
 */
-#define SDP_TRACE_ERROR(...)                     {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_SDP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define SDP_TRACE_WARNING(...)                   {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_SDP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define SDP_TRACE_API(...)                       {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_SDP, TRACE_TYPE_API, ##__VA_ARGS__);}
-#define SDP_TRACE_EVENT(...)                     {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_SDP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define SDP_TRACE_DEBUG(...)                     {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_SDP, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define SDP_TRACE_ERROR(...)                     {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_SDP, TRACE_TYPE_ERROR, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_SDP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define SDP_TRACE_WARNING(...)                   {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_SDP, TRACE_TYPE_WARNING, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_SDP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define SDP_TRACE_API(...)                       {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_SDP, TRACE_TYPE_API, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_SDP, TRACE_TYPE_API, ##__VA_ARGS__);}
+#define SDP_TRACE_EVENT(...)                     {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_SDP, TRACE_TYPE_EVENT, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_SDP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define SDP_TRACE_DEBUG(...)                     {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_SDP, TRACE_TYPE_DEBUG, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_SDP, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
 
 /* Define tracing for the RFCOMM unit
 */
-#define RFCOMM_TRACE_ERROR(...)                  {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_RFCOMM, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define RFCOMM_TRACE_WARNING(...)                {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_RFCOMM, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define RFCOMM_TRACE_API(...)                    {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_RFCOMM, TRACE_TYPE_API, ##__VA_ARGS__);}
-#define RFCOMM_TRACE_EVENT(...)                  {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_RFCOMM, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define RFCOMM_TRACE_DEBUG(...)                  {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_RFCOMM, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define RFCOMM_TRACE_ERROR(...)                  {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_RFCOMM, TRACE_TYPE_ERROR, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_RFCOMM, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define RFCOMM_TRACE_WARNING(...)                {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_RFCOMM, TRACE_TYPE_WARNING, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_RFCOMM, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define RFCOMM_TRACE_API(...)                    {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_RFCOMM, TRACE_TYPE_API, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_RFCOMM, TRACE_TYPE_API, ##__VA_ARGS__);}
+#define RFCOMM_TRACE_EVENT(...)                  {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_RFCOMM, TRACE_TYPE_EVENT, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_RFCOMM, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define RFCOMM_TRACE_DEBUG(...)                  {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_RFCOMM, TRACE_TYPE_DEBUG, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_RFCOMM, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
 
 /* Generic Access Profile traces */
-#define GAP_TRACE_ERROR(...)                     {if (gap_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_GAP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define GAP_TRACE_EVENT(...)                     {if (gap_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_GAP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define GAP_TRACE_API(...)                       {if (gap_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_GAP, TRACE_TYPE_API, ##__VA_ARGS__);}
-#define GAP_TRACE_WARNING(...)                   {if (gap_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_GAP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define GAP_TRACE_ERROR(...)                     {if (gap_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_GAP, TRACE_TYPE_ERROR, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_GAP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define GAP_TRACE_EVENT(...)                     {if (gap_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_GAP, TRACE_TYPE_EVENT, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_GAP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define GAP_TRACE_API(...)                       {if (gap_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_GAP, TRACE_TYPE_API, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_GAP, TRACE_TYPE_API, ##__VA_ARGS__);}
+#define GAP_TRACE_WARNING(...)                   {if (gap_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_GAP, TRACE_TYPE_WARNING, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_GAP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
 
 /* define traces for HID Host */
-#define HIDH_TRACE_ERROR(...)                     {if (hh_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_HID, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define HIDH_TRACE_WARNING(...)                   {if (hh_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_HID, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define HIDH_TRACE_API(...)                       {if (hh_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_HID, TRACE_TYPE_API, ##__VA_ARGS__);}
-#define HIDH_TRACE_EVENT(...)                     {if (hh_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_HID, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define HIDH_TRACE_DEBUG(...)                     {if (hh_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_HID, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define HIDH_TRACE_ERROR(...)                     {if (hh_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_HID, TRACE_TYPE_ERROR, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_HID, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define HIDH_TRACE_WARNING(...)                   {if (hh_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_HID, TRACE_TYPE_WARNING, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_HID, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define HIDH_TRACE_API(...)                       {if (hh_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_HID, TRACE_TYPE_API, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_HID, TRACE_TYPE_API, ##__VA_ARGS__);}
+#define HIDH_TRACE_EVENT(...)                     {if (hh_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_HID, TRACE_TYPE_EVENT, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_HID, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define HIDH_TRACE_DEBUG(...)                     {if (hh_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_HID, TRACE_TYPE_DEBUG, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_HID, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
 
 /* define traces for BNEP */
 
-#define BNEP_TRACE_ERROR(...)                     {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_BNEP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define BNEP_TRACE_WARNING(...)                   {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_BNEP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define BNEP_TRACE_API(...)                       {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_BNEP, TRACE_TYPE_API, ##__VA_ARGS__);}
-#define BNEP_TRACE_EVENT(...)                     {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_BNEP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define BNEP_TRACE_DEBUG(...)                     {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_BNEP, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define BNEP_TRACE_ERROR(...)                     {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_BNEP, TRACE_TYPE_ERROR, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_BNEP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define BNEP_TRACE_WARNING(...)                   {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_BNEP, TRACE_TYPE_WARNING, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_BNEP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define BNEP_TRACE_API(...)                       {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_BNEP, TRACE_TYPE_API, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_BNEP, TRACE_TYPE_API, ##__VA_ARGS__);}
+#define BNEP_TRACE_EVENT(...)                     {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_BNEP, TRACE_TYPE_EVENT, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_BNEP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define BNEP_TRACE_DEBUG(...)                     {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_BNEP, TRACE_TYPE_DEBUG, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_BNEP, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
 
 /* define traces for PAN */
 
-#define PAN_TRACE_ERROR(...)                     {if (pan_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_PAN, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define PAN_TRACE_WARNING(...)                   {if (pan_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_PAN, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define PAN_TRACE_API(...)                       {if (pan_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_PAN, TRACE_TYPE_API, ##__VA_ARGS__);}
-#define PAN_TRACE_EVENT(...)                     {if (pan_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_PAN, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define PAN_TRACE_DEBUG(...)                     {if (pan_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_PAN, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define PAN_TRACE_ERROR(...)                     {if (pan_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_PAN, TRACE_TYPE_ERROR, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_PAN, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define PAN_TRACE_WARNING(...)                   {if (pan_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_PAN, TRACE_TYPE_WARNING, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_PAN, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define PAN_TRACE_API(...)                       {if (pan_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_PAN, TRACE_TYPE_API, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_PAN, TRACE_TYPE_API, ##__VA_ARGS__);}
+#define PAN_TRACE_EVENT(...)                     {if (pan_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_PAN, TRACE_TYPE_EVENT, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_PAN, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define PAN_TRACE_DEBUG(...)                     {if (pan_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_PAN, TRACE_TYPE_DEBUG, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_PAN, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
 
 /* Define tracing for the A2DP profile
 */
-#define A2D_TRACE_ERROR(...)                      {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_A2D, TRACE_TYPE_ERROR,##__VA_ARGS__);}
-#define A2D_TRACE_WARNING(...)                    {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_A2D, TRACE_TYPE_WARNING,##__VA_ARGS__);}
-#define A2D_TRACE_EVENT(...)                      {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_A2D, TRACE_TYPE_EVENT,##__VA_ARGS__);}
-#define A2D_TRACE_DEBUG(...)                      {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_A2D, TRACE_TYPE_DEBUG,##__VA_ARGS__);}
-#define A2D_TRACE_API(...)                        {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_A2D, TRACE_TYPE_API,##__VA_ARGS__);}
+#define A2D_TRACE_ERROR(...)                      {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_A2D, TRACE_TYPE_ERROR,##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_A2D, TRACE_TYPE_ERROR,##__VA_ARGS__);}
+#define A2D_TRACE_WARNING(...)                    {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_A2D, TRACE_TYPE_WARNING,##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_A2D, TRACE_TYPE_WARNING,##__VA_ARGS__);}
+#define A2D_TRACE_EVENT(...)                      {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_A2D, TRACE_TYPE_EVENT,##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_A2D, TRACE_TYPE_EVENT,##__VA_ARGS__);}
+#define A2D_TRACE_DEBUG(...)                      {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_A2D, TRACE_TYPE_DEBUG,##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_A2D, TRACE_TYPE_DEBUG,##__VA_ARGS__);}
+#define A2D_TRACE_API(...)                        {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_A2D, TRACE_TYPE_API,##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_A2D, TRACE_TYPE_API,##__VA_ARGS__);}
 
 /* AVDTP
 */
-#define AVDT_TRACE_ERROR(...)                     {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define AVDT_TRACE_WARNING(...)                   {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define AVDT_TRACE_EVENT(...)                     {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define AVDT_TRACE_DEBUG(...)                     {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
-#define AVDT_TRACE_API(...)                       {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_API, ##__VA_ARGS__);}
+#define AVDT_TRACE_ERROR(...)                     {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_ERROR, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define AVDT_TRACE_WARNING(...)                   {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_WARNING, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define AVDT_TRACE_EVENT(...)                     {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_EVENT, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define AVDT_TRACE_DEBUG(...)                     {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_DEBUG, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define AVDT_TRACE_API(...)                       {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_API, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_API, ##__VA_ARGS__);}
 
 /* Define tracing for the AVCTP protocol
 */
-#define AVCT_TRACE_ERROR(...)                     {if (avct_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define AVCT_TRACE_WARNING(...)                   {if (avct_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define AVCT_TRACE_EVENT(...)                     {if (avct_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define AVCT_TRACE_DEBUG(...)                     {if (avct_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
-#define AVCT_TRACE_API(...)                       {if (avct_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_API, ##__VA_ARGS__);}
+#define AVCT_TRACE_ERROR(...)                     {if (avct_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_ERROR, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define AVCT_TRACE_WARNING(...)                   {if (avct_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_WARNING, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define AVCT_TRACE_EVENT(...)                     {if (avct_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_EVENT, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define AVCT_TRACE_DEBUG(...)                     {if (avct_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_DEBUG, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define AVCT_TRACE_API(...)                       {if (avct_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_API, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_API, ##__VA_ARGS__);}
 
 /* Define tracing for the AVRCP profile
 */
-#define AVRC_TRACE_ERROR(...)                      {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define AVRC_TRACE_WARNING(...)                    {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define AVRC_TRACE_EVENT(...)                      {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define AVRC_TRACE_DEBUG(...)                      {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
-#define AVRC_TRACE_API(...)                        {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_API, ##__VA_ARGS__);}
+#define AVRC_TRACE_ERROR(...)                      {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_ERROR, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define AVRC_TRACE_WARNING(...)                    {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_WARNING, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define AVRC_TRACE_EVENT(...)                      {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_EVENT, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define AVRC_TRACE_DEBUG(...)                      {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_DEBUG, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define AVRC_TRACE_API(...)                        {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_API, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_API, ##__VA_ARGS__);}
 
 /* MCAP
 */
-#define MCA_TRACE_ERROR(...)                     {if (mca_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_MCA, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define MCA_TRACE_WARNING(...)                   {if (mca_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_MCA, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define MCA_TRACE_EVENT(...)                     {if (mca_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_MCA, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define MCA_TRACE_DEBUG(...)                     {if (mca_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_MCA, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
-#define MCA_TRACE_API(...)                       {if (mca_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_MCA, TRACE_TYPE_API, ##__VA_ARGS__);}
+#define MCA_TRACE_ERROR(...)                     {if (mca_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_MCA, TRACE_TYPE_ERROR, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_MCA, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define MCA_TRACE_WARNING(...)                   {if (mca_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_MCA, TRACE_TYPE_WARNING, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_MCA, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define MCA_TRACE_EVENT(...)                     {if (mca_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_MCA, TRACE_TYPE_EVENT, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_MCA, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define MCA_TRACE_DEBUG(...)                     {if (mca_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_MCA, TRACE_TYPE_DEBUG, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_MCA, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define MCA_TRACE_API(...)                       {if (mca_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_MCA, TRACE_TYPE_API, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_MCA, TRACE_TYPE_API, ##__VA_ARGS__);}
 
 /* Define tracing for the ATT/GATT unit
 */
-#define GATT_TRACE_ERROR(...)                     {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_ATT, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define GATT_TRACE_WARNING(...)                   {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_ATT, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define GATT_TRACE_API(...)                       {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_ATT, TRACE_TYPE_API, ##__VA_ARGS__);}
-#define GATT_TRACE_EVENT(...)                     {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_ATT, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define GATT_TRACE_DEBUG(...)                     {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_ATT, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define GATT_TRACE_ERROR(...)                     {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_ATT, TRACE_TYPE_ERROR, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_ATT, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define GATT_TRACE_WARNING(...)                   {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_ATT, TRACE_TYPE_WARNING, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_ATT, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define GATT_TRACE_API(...)                       {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_ATT, TRACE_TYPE_API, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_ATT, TRACE_TYPE_API, ##__VA_ARGS__);}
+#define GATT_TRACE_EVENT(...)                     {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_ATT, TRACE_TYPE_EVENT, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_ATT, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define GATT_TRACE_DEBUG(...)                     {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_ATT, TRACE_TYPE_DEBUG, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_ATT, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
 
 /* Define tracing for the SMP unit
 */
-#define SMP_TRACE_ERROR(...)                     {if (smp_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_SMP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define SMP_TRACE_WARNING(...)                   {if (smp_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_SMP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define SMP_TRACE_API(...)                       {if (smp_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_SMP, TRACE_TYPE_API, ##__VA_ARGS__);}
-#define SMP_TRACE_EVENT(...)                     {if (smp_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_SMP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define SMP_TRACE_DEBUG(...)                     {if (smp_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_SMP, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define SMP_TRACE_ERROR(...)                     {if (smp_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_TRACE(TRACE_LAYER_SMP, TRACE_TYPE_ERROR, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_SMP, TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define SMP_TRACE_WARNING(...)                   {if (smp_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_TRACE(TRACE_LAYER_SMP, TRACE_TYPE_WARNING, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_SMP, TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define SMP_TRACE_API(...)                       {if (smp_cb.trace_level >= BT_TRACE_LEVEL_API) BT_TRACE(TRACE_LAYER_SMP, TRACE_TYPE_API, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_SMP, TRACE_TYPE_API, ##__VA_ARGS__);}
+#define SMP_TRACE_EVENT(...)                     {if (smp_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_TRACE(TRACE_LAYER_SMP, TRACE_TYPE_EVENT, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_SMP, TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define SMP_TRACE_DEBUG(...)                     {if (smp_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_TRACE(TRACE_LAYER_SMP, TRACE_TYPE_DEBUG, ##__VA_ARGS__); else VND_TRACE(TRACE_LAYER_SMP, TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
 
 extern UINT8 btif_trace_level;
+extern UINT8 audio_latency_trace_level;
 
 /* define traces for application */
-#define BTIF_TRACE_ERROR(...)                    {if (btif_trace_level >= BT_TRACE_LEVEL_ERROR) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define BTIF_TRACE_WARNING(...)                  {if (btif_trace_level >= BT_TRACE_LEVEL_WARNING) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define BTIF_TRACE_API(...)                      {if (btif_trace_level >= BT_TRACE_LEVEL_API) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_API, ##__VA_ARGS__);}
-#define BTIF_TRACE_EVENT(...)                    {if (btif_trace_level >= BT_TRACE_LEVEL_EVENT) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define BTIF_TRACE_DEBUG(...)                    {if (btif_trace_level >= BT_TRACE_LEVEL_DEBUG) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define BTIF_TRACE_IMP(...)                      {LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define BTIF_TRACE_ERROR(...)                    {if (btif_trace_level >= BT_TRACE_LEVEL_ERROR) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_ERROR, ##__VA_ARGS__); else vnd_LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define BTIF_TRACE_WARNING(...)                  {if (btif_trace_level >= BT_TRACE_LEVEL_WARNING) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_WARNING, ##__VA_ARGS__); else vnd_LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_WARNING, ##__VA_ARGS__);}
+#define BTIF_TRACE_API(...)                      {if (btif_trace_level >= BT_TRACE_LEVEL_API) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_API, ##__VA_ARGS__); else vnd_LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_API, ##__VA_ARGS__);}
+#define BTIF_TRACE_EVENT(...)                    {if (btif_trace_level >= BT_TRACE_LEVEL_EVENT) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_EVENT, ##__VA_ARGS__); else vnd_LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define BTIF_TRACE_DEBUG(...)                    {if (btif_trace_level >= BT_TRACE_LEVEL_DEBUG) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, ##__VA_ARGS__); else vnd_LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
 #define BTIF_TRACE_VERBOSE(...)                  {if (btif_trace_level >= BT_TRACE_LEVEL_VERBOSE) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
 
+
 /* define traces for application */
-#define APPL_TRACE_ERROR(...)                    {if (appl_trace_level >= BT_TRACE_LEVEL_ERROR) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_ERROR, ##__VA_ARGS__);}
-#define APPL_TRACE_WARNING(...)                  {if (appl_trace_level >= BT_TRACE_LEVEL_WARNING) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_WARNING, ##__VA_ARGS__);}
-#define APPL_TRACE_API(...)                      {if (appl_trace_level >= BT_TRACE_LEVEL_API) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_API, ##__VA_ARGS__);}
-#define APPL_TRACE_EVENT(...)                    {if (appl_trace_level >= BT_TRACE_LEVEL_EVENT) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_EVENT, ##__VA_ARGS__);}
-#define APPL_TRACE_DEBUG(...)                    {if (appl_trace_level >= BT_TRACE_LEVEL_DEBUG) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define APPL_TRACE_IMP(...)                      {LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define APPL_TRACE_ERROR(...)                    {if (appl_trace_level >= BT_TRACE_LEVEL_ERROR) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_ERROR, ##__VA_ARGS__); else vnd_LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define APPL_TRACE_WARNING(...)                  {if (appl_trace_level >= BT_TRACE_LEVEL_WARNING) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_WARNING, ##__VA_ARGS__); else vnd_LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_ERROR, ##__VA_ARGS__);}
+#define APPL_TRACE_API(...)                      {if (appl_trace_level >= BT_TRACE_LEVEL_API) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_API, ##__VA_ARGS__); else vnd_LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_API, ##__VA_ARGS__);}
+#define APPL_TRACE_EVENT(...)                    {if (appl_trace_level >= BT_TRACE_LEVEL_EVENT) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_EVENT, ##__VA_ARGS__); else vnd_LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_EVENT, ##__VA_ARGS__);}
+#define APPL_TRACE_DEBUG(...)                    {if (appl_trace_level >= BT_TRACE_LEVEL_DEBUG) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, ##__VA_ARGS__); else vnd_LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
 #define APPL_TRACE_VERBOSE(...)                  {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
+#define APPL_TRACE_LATENCY_AUDIO(...)            {if (audio_latency_trace_level >= BT_TRACE_LEVEL_VERBOSE) LogMsg(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, ##__VA_ARGS__);}
 
 /* Simplified Trace Helper Macro
 */
@@ -414,3 +424,5 @@
 extern UINT8 appl_trace_level;
 
 void LogMsg (UINT32 trace_set_mask, const char *fmt_str, ...);
+void vnd_LogMsg (UINT32 trace_set_mask, const char *fmt_str, ...);
+void vnd_GenerateLogs();
diff --git a/include/logging.h b/include/logging.h
new file mode 100644
index 0000000..bd70b39
--- /dev/null
+++ b/include/logging.h
@@ -0,0 +1,45 @@
+/*********************************************************************
+*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*   * Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   * Redistributions in binary form must reproduce the above
+*     copyright notice, this list of conditions and the following
+*     disclaimer in the documentation and/or other materials provided
+*     with the distribution.
+*   * Neither the name of The Linux Foundation nor the names of its
+*     contributors may be used to endorse or promote products derived
+*     from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+************************************************************************/
+
+#include <stdio.h>
+#include "bt_types.h"
+
+__BEGIN_DECLS
+
+typedef struct {
+
+    size_t size;
+    void (*setLog)( const char *log_layer, UINT16 log_level);
+} btstacklog_interface_t;
+
+__END_DECLS
+
diff --git a/include/stack_config.h b/include/stack_config.h
index b5278ce..837fdbe 100644
--- a/include/stack_config.h
+++ b/include/stack_config.h
@@ -32,6 +32,7 @@
 typedef struct {
   const char *(*get_btsnoop_log_path)(void);
   bool (*get_btsnoop_turned_on)(void);
+  void (*get_btsnoop_ext_options)(bool *hci_ext_dump_enabled, bool *btsnoop_conf_from_file);
   bool (*get_btsnoop_should_save_last)(void);
   bool (*get_trace_config_enabled)(void);
   bool (*get_pts_secure_only_mode)(void);
@@ -39,6 +40,7 @@
   bool (*get_pts_crosskey_sdp_disable)(void);
   const char* (*get_pts_smp_options)(void);
   int (*get_pts_smp_failure_case)(void);
+  bool (*get_pts_le_nonconn_adv_enabled)(void);
   config_t *(*get_all)(void);
 } stack_config_t;
 
diff --git a/main/Android.mk b/main/Android.mk
index 25a0358..594b4d2 100644
--- a/main/Android.mk
+++ b/main/Android.mk
@@ -26,6 +26,16 @@
 LOCAL_SRC_FILES+= \
 	../udrv/ulinux/uipc.c
 
+ifeq ($(BOARD_USES_WIPOWER),true)
+ifneq ($(TARGET_SUPPORTS_WEARABLES),true)
+LOCAL_SRC_FILES += \
+       ../../../vendor/qcom/opensource/bluetooth/wipower-host/core/src/wipower.c
+else
+LOCAL_SRC_FILES += \
+       ../../../device/qcom/msm8909w/opensource/bluetooth/wipower-host/core/src/wipower.c
+endif
+endif
+
 LOCAL_C_INCLUDES+= . \
 	$(LOCAL_PATH)/../ \
 	$(LOCAL_PATH)/../bta/include \
@@ -53,7 +63,20 @@
 	$(LOCAL_PATH)/../utils/include \
 	$(bluetooth_C_INCLUDES) \
 	external/tinyxml2 \
-	external/zlib
+    external/zlib \
+    $(call include-path-for, audio-utils)
+
+ifeq ($(BOARD_USES_WIPOWER),true)
+ifneq ($(TARGET_SUPPORTS_WEARABLES),true)
+LOCAL_C_INCLUDES+= \
+       vendor/qcom/opensource/bluetooth/hal/include \
+       vendor/qcom/opensource/bluetooth/wipower-host/core/include
+else
+LOCAL_C_INCLUDES+= \
+       device/qcom/msm8909w/opensource/bluetooth/hal/include \
+       device/qcom/msm8909w/opensource/bluetooth/wipower-host/core/include
+endif
+endif
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
@@ -64,7 +87,8 @@
     libprotobuf-cpp-full \
     libmedia \
     libutils \
-    libchrome
+    libchrome \
+    libaudioutils
 
 LOCAL_STATIC_LIBRARIES := \
     libtinyxml2 \
@@ -98,6 +122,7 @@
 LOCAL_REQUIRED_MODULES := \
     bt_did.conf \
     bt_stack.conf \
+    interop_database.conf \
     libbt-hci \
     libbt-vendor
 
diff --git a/main/bte_logmsg.c b/main/bte_logmsg.c
index 4a59eac..2d6d208 100644
--- a/main/bte_logmsg.c
+++ b/main/bte_logmsg.c
@@ -25,6 +25,7 @@
 #include <stdarg.h>
 #include <sys/time.h>
 #include <time.h>
+#include <dlfcn.h>
 
 #include "avrc_api.h"
 #include "bta_api.h"
@@ -66,6 +67,10 @@
 #define BTE_LOG_BUF_SIZE  1024
 #endif
 
+#define VND_PKT_SIZE_BLOCKS 4
+#define VND_PKT_HEADER_SIZE 5 //(VND_PKT_SIZE_BLOCKS + 1)
+#define VND_PKT_BODY_SIZE 1021
+
 #define BTE_LOG_MAX_SIZE  (BTE_LOG_BUF_SIZE - 12)
 
 #define MSG_BUFFER_OFFSET 0
@@ -125,6 +130,7 @@
 static uint8_t BTAPP_SetTraceLevel(uint8_t new_level);
 static uint8_t BTIF_SetTraceLevel(uint8_t new_level);
 static uint8_t BTU_SetTraceLevel(uint8_t new_level);
+static uint8_t AUDIO_Latency_SetTraceLevel(uint8_t new_level);
 
 /* make sure list is order by increasing layer id!!! */
 static tBTTRC_FUNC_MAP bttrc_set_level_map[] = {
@@ -154,6 +160,9 @@
   {BTTRC_ID_STK_GATT, BTTRC_ID_STK_GATT, GATT_SetTraceLevel, "TRC_GATT", DEFAULT_CONF_TRACE_LEVEL},
   {BTTRC_ID_STK_SMP, BTTRC_ID_STK_SMP, SMP_SetTraceLevel, "TRC_SMP", DEFAULT_CONF_TRACE_LEVEL},
 #endif
+#if (BT_TRACE_LATENCY_AUDIO == TRUE)
+    {BTTRC_ID_LATENCY_AUDIO, BTTRC_ID_LATENCY_AUDIO, AUDIO_Latency_SetTraceLevel, "TRC_LATENCY_AUDIO", DEFAULT_CONF_TRACE_LEVEL},
+#endif
 
   /* LayerIDs for BTA, currently everything maps onto appl_trace_level.
    */
@@ -194,6 +203,26 @@
   }
 }
 
+void vnd_LogMsg(uint32_t trace_set_mask, const char *fmt_str, ...) {
+  int trace_layer = TRACE_GET_LAYER(trace_set_mask);
+  const char *tag;
+  if (trace_layer >= TRACE_LAYER_MAX_NUM)
+    trace_layer = 0;
+
+  tag = bt_layer_tags[trace_layer];
+
+  va_list ap;
+  va_start(ap, fmt_str);
+  if(logger_interface)
+    logger_interface->send_log_msg(tag, fmt_str, ap);
+  va_end(ap);
+}
+
+void vnd_GenerateLogs() {
+  if(logger_interface)
+    logger_interface->send_event(GENERATE_VND_LOG_SIGNAL);
+}
+
 /* this function should go into BTAPP_DM for example */
 static uint8_t BTAPP_SetTraceLevel(uint8_t new_level) {
   if (new_level != 0xFF)
@@ -209,6 +238,15 @@
   return btif_trace_level;
 }
 
+static uint8_t AUDIO_Latency_SetTraceLevel( uint8_t new_level )
+{
+    if (new_level != 0xFF)
+    audio_latency_trace_level = new_level;
+
+    return (audio_latency_trace_level);
+}
+
+
 static uint8_t BTU_SetTraceLevel(uint8_t new_level) {
   if (new_level != 0xFF)
     btu_trace_level = new_level;
@@ -236,7 +274,6 @@
     LOG_INFO(LOG_TAG, "using compile default trace settings");
     return NULL;
   }
-
   load_levels_from_config(stack_config->get_all());
   return NULL;
 }
@@ -252,3 +289,43 @@
     NULL
   }
 };
+
+/********************************************************************************
+ **
+ **    Function Name:    BTA_setStackLog
+ **
+ **    Purpose:          Set the trace level of the different layers of stack
+                         based on the stack layer and level as input
+ **
+ **    Input Parameters: const char* log_layer, int log_level
+                         Example : TRC_HCI, 5
+ **
+ **    Returns:          void
+ **
+ *********************************************************************************/
+
+void BTA_setStackLog( const char* log_layer, int log_level)
+{
+    const tBTTRC_FUNC_MAP *p_f_map;
+    int new_level = 0;
+    int layer_found = 0;
+    p_f_map = &bttrc_set_level_map[0];
+
+    while ( 0 != p_f_map->layer_id_start )
+    {
+
+        if( (NULL != p_f_map->p_f) && !strcmp( p_f_map->trc_name, log_layer))
+        {
+            new_level = p_f_map->p_f(log_level);
+            LOG_INFO("BTA_setStackLog: New trace level set for layer %s is %d", log_layer, new_level);
+            layer_found = 1;
+            break;
+        }
+        p_f_map++;
+    }
+
+    if ( layer_found == 0 )
+    {
+        LOG_INFO("BTA_setStackLog: Unable to set Layer %s with level %d. Layer not found", log_layer, log_level);
+    }
+}
diff --git a/main/bte_main.c b/main/bte_main.c
index da36056..7ab0440 100644
--- a/main/bte_main.c
+++ b/main/bte_main.c
@@ -267,3 +267,22 @@
         osi_free(p_msg);
     }
 }
+/******************************************************************************
+**
+** Function         bte_ssr_cleanup
+**
+** Description      sends PWR_OFF to vendor library so that harware would be
+**                  turned off as part of hardware subsystem crash
+**
+** Returns          None
+**
+******************************************************************************/
+void bte_ssr_cleanup(int reason)
+{
+    APPL_TRACE_DEBUG("%s", __FUNCTION__);
+    if (hci != NULL) {
+        hci->ssr_cleanup(reason);
+    } else {
+        APPL_TRACE_ERROR("%s hci is NULL", __FUNCTION__);
+    }
+}
diff --git a/main/stack_config.c b/main/stack_config.c
index df0e0ef..f12a789 100644
--- a/main/stack_config.c
+++ b/main/stack_config.c
@@ -27,6 +27,8 @@
 
 const char *BTSNOOP_LOG_PATH_KEY = "BtSnoopFileName";
 const char *BTSNOOP_TURNED_ON_KEY = "BtSnoopLogOutput";
+const char *BTSNOOP_EXT_DUMP_KEY = "BtSnoopExtDump";
+const char *BTSNOOP_CONFIG_FROM_FILE_KEY = "BtSnoopConfigFromFile";
 const char *BTSNOOP_SHOULD_SAVE_LAST_KEY = "BtSnoopSaveLog";
 const char *TRACE_CONFIG_ENABLED_KEY = "TraceConf";
 const char *PTS_SECURE_ONLY_MODE = "PTS_SecurePairOnly";
@@ -34,6 +36,7 @@
 const char *PTS_DISABLE_SDP_LE_PAIR = "PTS_DisableSDPOnLEPair";
 const char *PTS_SMP_PAIRING_OPTIONS_KEY = "PTS_SmpOptions";
 const char *PTS_SMP_FAILURE_CASE_KEY = "PTS_SmpFailureCase";
+const char *PTS_LE_NONCONN_ADV_MODE = "PTS_EnableNonConnAdvMode";
 
 static config_t *config;
 
@@ -115,6 +118,15 @@
   return config_get_int(config, CONFIG_DEFAULT_SECTION, PTS_SMP_FAILURE_CASE_KEY, 0);
 }
 
+static void get_btsnoop_ext_options(bool *hci_ext_dump_enabled, bool *btsnoop_conf_from_file) {
+  *hci_ext_dump_enabled = config_get_bool(config, CONFIG_DEFAULT_SECTION, BTSNOOP_EXT_DUMP_KEY, false);
+  *btsnoop_conf_from_file = config_get_bool(config, CONFIG_DEFAULT_SECTION, BTSNOOP_CONFIG_FROM_FILE_KEY, false);
+}
+
+static bool get_pts_le_nonconn_adv_enabled(void) {
+  return config_get_bool(config, CONFIG_DEFAULT_SECTION, PTS_LE_NONCONN_ADV_MODE, false);
+}
+
 static config_t *get_all(void) {
   return config;
 }
@@ -122,6 +134,7 @@
 const stack_config_t interface = {
   get_btsnoop_log_path,
   get_btsnoop_turned_on,
+  get_btsnoop_ext_options,
   get_btsnoop_should_save_last,
   get_trace_config_enabled,
   get_pts_secure_only_mode,
@@ -129,6 +142,7 @@
   get_pts_crosskey_sdp_disable,
   get_pts_smp_options,
   get_pts_smp_failure_case,
+  get_pts_le_nonconn_adv_enabled,
   get_all
 };
 
diff --git a/osi/Android.mk b/osi/Android.mk
index d1937d1..bab6cd1 100644
--- a/osi/Android.mk
+++ b/osi/Android.mk
@@ -51,7 +51,8 @@
     ./src/socket_utils/socket_local_server.c \
     ./src/thread.c \
     ./src/time.c \
-    ./src/wakelock.c
+    ./src/wakelock.c \
+    ./src/vnd_log.c
 
 btosiCommonTestSrc := \
     ./test/AlarmTestHarness.cpp \
diff --git a/osi/include/list.h b/osi/include/list.h
index a510178..82c6b5a 100644
--- a/osi/include/list.h
+++ b/osi/include/list.h
@@ -16,6 +16,7 @@
 // user defined value passed into |list_foreach|.
 // Callback must return true to continue iterating or false to stop iterating.
 typedef bool (*list_iter_cb)(void *data, void *context);
+typedef bool (*list_iter_cb_ext)(void *data, void *cb_data);
 
 // Returns a new, empty list. Returns NULL if not enough memory could be allocated
 // for the list structure. The returned list must be freed with |list_free|. The
@@ -91,6 +92,7 @@
 // there will be no callback for the newly-inserted node. Neither |list| nor
 // |callback| may be NULL.
 list_node_t *list_foreach(const list_t *list, list_iter_cb callback, void *context);
+void list_foreach_ext(const list_t *list, list_iter_cb_ext callback, void *cb_data);
 
 // Returns an iterator to the first element in |list|. |list| may not be NULL.
 // The returned iterator is valid as long as it does not equal the value returned
diff --git a/osi/include/log.h b/osi/include/log.h
index 738462e..a579ded 100644
--- a/osi/include/log.h
+++ b/osi/include/log.h
@@ -17,6 +17,12 @@
  ******************************************************************************/
 
 #pragma once
+#include <string.h>
+#include <stdbool.h>
+#include "include/bt_logger_lib.h"
+
+extern bt_logger_interface_t *logger_interface;
+extern bool bt_logger_enabled;
 
 /*
  * TODO(armansito): Work-around until we figure out a way to generate logs in a
@@ -39,14 +45,16 @@
 
 #include <cutils/log.h>
 
+//#define VNDLOG(tag, fmt, ## args) if(logger_interface)logger_interface->send_log_data(tag, fmt, ## args)
+
 #if LOG_NDEBUG
 #define LOG_VERBOSE(...) ((void)0)
 #else  // LOG_NDEBUG
 #define LOG_VERBOSE(tag, fmt, args...) ALOG(LOG_VERBOSE, tag, fmt, ## args)
 #endif  // !LOG_NDEBUG
-#define LOG_DEBUG(tag, fmt, args...)   ALOG(LOG_DEBUG, tag, fmt, ## args )
-#define LOG_INFO(tag, fmt, args...)    ALOG(LOG_INFO, tag, fmt, ## args)
-#define LOG_WARN(tag, fmt, args...)    ALOG(LOG_WARN, tag, fmt, ## args)
-#define LOG_ERROR(tag, fmt, args...)   ALOG(LOG_ERROR, tag, fmt, ## args)
+#define LOG_DEBUG(tag, fmt, args...)   {if(logger_interface)logger_interface->send_log_data(tag, fmt, ## args);ALOG(LOG_DEBUG, tag, fmt, ## args);}
+#define LOG_INFO(tag, fmt, args...)    {if(logger_interface)logger_interface->send_log_data(tag, fmt, ## args);ALOG(LOG_INFO, tag, fmt, ## args);}
+#define LOG_WARN(tag, fmt, args...)    {if(logger_interface)logger_interface->send_log_data(tag, fmt, ## args);ALOG(LOG_WARN, tag, fmt, ## args);}
+#define LOG_ERROR(tag, fmt, args...)   {if(logger_interface)logger_interface->send_log_data(tag, fmt, ## args);ALOG(LOG_ERROR, tag, fmt, ## args);}
 
 #endif  /* defined(OS_GENERIC) */
diff --git a/osi/src/alarm.c b/osi/src/alarm.c
index ab4ed12..7ac6434 100644
--- a/osi/src/alarm.c
+++ b/osi/src/alarm.c
@@ -94,13 +94,11 @@
 // unit tests to run faster. It should not be modified by production code.
 int64_t TIMER_INTERVAL_FOR_WAKELOCK_IN_MS = 3000;
 static const clockid_t CLOCK_ID = CLOCK_BOOTTIME;
-
 #if defined(KERNEL_MISSING_CLOCK_BOOTTIME_ALARM) && (KERNEL_MISSING_CLOCK_BOOTTIME_ALARM == TRUE)
 static const clockid_t CLOCK_ID_ALARM = CLOCK_BOOTTIME;
 #else
 static const clockid_t CLOCK_ID_ALARM = CLOCK_BOOTTIME_ALARM;
 #endif
-
 // This mutex ensures that the |alarm_set|, |alarm_cancel|, and alarm callback
 // functions execute serially and not concurrently. As a result, this mutex
 // also protects the |alarms| list.
@@ -606,6 +604,7 @@
     alarm->deadline = 0;
     alarm->callback = NULL;
     alarm->data = NULL;
+    alarm->queue = NULL;
   }
 
   pthread_mutex_lock(&alarm->callback_lock);
@@ -632,19 +631,21 @@
 // thread for that alarm.
 static void callback_dispatch(UNUSED_ATTR void *context) {
   while (true) {
+    period_ms_t just_now;
     semaphore_wait(alarm_expired);
     if (!dispatcher_thread_active)
       break;
 
     pthread_mutex_lock(&monitor);
     alarm_t *alarm;
+    just_now = now();
 
     // Take into account that the alarm may get cancelled before we get to it.
     // We're done here if there are no alarms or the alarm at the front is in
     // the future. Release the monitor lock and exit right away since there's
     // nothing left to do.
     if (list_is_empty(alarms) ||
-        (alarm = list_front(alarms))->deadline > now()) {
+        (alarm = list_front(alarms))->deadline > just_now) {
       reschedule_root_alarm();
       pthread_mutex_unlock(&monitor);
       continue;
@@ -652,6 +653,9 @@
 
     list_remove(alarms, alarm);
 
+    if(just_now - alarm->deadline > 1000)
+      LOG_DEBUG(LOG_TAG, "%s Delay in timer callback", __func__);
+
     if (alarm->is_periodic) {
       alarm->prev_deadline = alarm->deadline;
       schedule_next_instance(alarm);
diff --git a/osi/src/allocation_tracker.c b/osi/src/allocation_tracker.c
index b4e1a84..c5cb6cd 100644
--- a/osi/src/allocation_tracker.c
+++ b/osi/src/allocation_tracker.c
@@ -133,10 +133,14 @@
     hash_map_set(allocations, return_ptr, allocation);
   }
 
-  allocation->allocator_id = allocator_id;
-  allocation->freed = false;
-  allocation->size = requested_size;
-  allocation->ptr = return_ptr;
+  if (allocation) {
+    allocation->allocator_id = allocator_id;
+    allocation->freed = false;
+    allocation->size = requested_size;
+    allocation->ptr = return_ptr;
+  } else {
+    LOG_ERROR(LOG_TAG, "%s Memory not allocated for allocation." ,__func__);
+  }
 
   pthread_mutex_unlock(&lock);
 
diff --git a/osi/src/config.c b/osi/src/config.c
index 9145ce6..e2c577c 100644
--- a/osi/src/config.c
+++ b/osi/src/config.c
@@ -34,6 +34,7 @@
 #include "osi/include/allocator.h"
 #include "osi/include/list.h"
 #include "osi/include/log.h"
+#include "osi/include/compat.h"
 #include "log/log.h"
 
 typedef struct {
@@ -214,7 +215,11 @@
   section_t *sec = section_find(config, section);
   if (!sec) {
     sec = section_new(section);
-    list_append(config->sections, sec);
+    if (sec)
+      list_append(config->sections, sec);
+    else {
+      LOG_ERROR(LOG_TAG,"%s: Unable to allocate memory for section", __func__);
+    }
   }
 
   size_t value_len = strlen(value);
@@ -227,19 +232,21 @@
     }
   }
 
-  for (const list_node_t *node = list_begin(sec->entries); node != list_end(sec->entries); node = list_next(node)) {
-    entry_t *entry = list_node(node);
-    if (!strcmp(entry->key, key)) {
-      osi_free(entry->value);
-      entry->value = osi_strdup(value_no_newline);
-      osi_free(value_no_newline);
-      return;
+  if (sec) {
+    for (const list_node_t *node = list_begin(sec->entries); node != list_end(sec->entries); node = list_next(node)) {
+      entry_t *entry = list_node(node);
+      if (!strcmp(entry->key, key)) {
+        osi_free(entry->value);
+        entry->value = osi_strdup(value_no_newline);
+        osi_free(value_no_newline);
+        return;
+      }
     }
-  }
 
-  entry_t *entry = entry_new(key, value_no_newline);
-  osi_free(value_no_newline);
-  list_append(sec->entries, entry);
+    entry_t *entry = entry_new(key, value_no_newline);
+    osi_free(value_no_newline);
+    list_append(sec->entries, entry);
+  }
 }
 
 bool config_remove_section(config_t *config, const char *section) {
@@ -333,7 +340,12 @@
 
   for (const list_node_t *node = list_begin(config->sections); node != list_end(config->sections); node = list_next(node)) {
     const section_t *section = (const section_t *)list_node(node);
-    if (fprintf(fp, "[%s]\n", section->name) < 0) {
+    if (section->name[0] == '#') {
+        if (fprintf(fp, "%s", section->name) < 0) {
+            LOG_ERROR(LOG_TAG, "%s unable to write to file '%s': %s", __func__, temp_filename, strerror(errno));
+            goto error;
+        }
+    } else if (fprintf(fp, "[%s]\n", section->name) < 0) {
       LOG_ERROR(LOG_TAG, "%s unable to write to file '%s': %s", __func__, temp_filename, strerror(errno));
       goto error;
     }
@@ -424,31 +436,55 @@
   assert(config != NULL);
 
   int line_num = 0;
-  char line[1024];
-  char section[1024];
+  char line[1024] = { '\0' };
+  char section[1024] = { '\0' };
+  char comment[1024] = { '\0' };
+  bool skip_entries = false;
   strcpy(section, CONFIG_DEFAULT_SECTION);
 
   while (fgets(line, sizeof(line), fp)) {
     char *line_ptr = trim(line);
     ++line_num;
 
-    // Skip blank and comment lines.
-    if (*line_ptr == '\0' || *line_ptr == '#')
+    // ignore the line if the line length is more than 1023
+    if (strlen(line) == 1023){
+        int ch = '\0';
+        // read until next line or EOF
+        while(((ch = fgetc(fp)) != EOF) && (ch != '\n'));
+        continue;
+    }
+
+    // Skip blanks.
+    if (*line_ptr == '\0')
       continue;
 
-    if (*line_ptr == '[') {
+    if (*line_ptr == '#') {
+        strlcpy(comment, line_ptr, 1024);
+
+        if(!section_find(config, comment)) {
+            section_t *sec = section_new(comment);
+            if (sec)
+                list_append(config->sections, sec);
+        }
+    } else if (*line_ptr == '[') {
       size_t len = strlen(line_ptr);
       if (line_ptr[len - 1] != ']') {
         LOG_DEBUG(LOG_TAG, "%s unterminated section name on line %d.", __func__, line_num);
-        return false;
+        skip_entries = true;
+        continue;
       }
       strncpy(section, line_ptr + 1, len - 2);
       section[len - 2] = '\0';
+      skip_entries = false;
     } else {
       char *split = strchr(line_ptr, '=');
+      if(skip_entries) {
+        LOG_DEBUG(LOG_TAG, "%s skip entries due invalid section line %d.", __func__, line_num);
+        continue;
+      }
       if (!split) {
         LOG_DEBUG(LOG_TAG, "%s no key/value separator found on line %d.", __func__, line_num);
-        return false;
+        continue;
       }
 
       *split = '\0';
diff --git a/osi/src/eager_reader.c b/osi/src/eager_reader.c
index 07a944c..86fcecc 100644
--- a/osi/src/eager_reader.c
+++ b/osi/src/eager_reader.c
@@ -259,9 +259,9 @@
     // the semaphore by the number of bytes we just read
     eventfd_write(reader->bytes_available_fd, bytes_read);
   } else {
-    if (bytes_read == 0)
+    if (bytes_read == 0){
       LOG_WARN(LOG_TAG, "%s fd said bytes existed, but none were found.", __func__);
-    else
+    } else
       LOG_WARN(LOG_TAG, "%s unable to read from file descriptor: %s", __func__, strerror(errno));
 
     reader->allocator->free(buffer);
diff --git a/osi/src/list.c b/osi/src/list.c
index 9468579..4688ce9 100644
--- a/osi/src/list.c
+++ b/osi/src/list.c
@@ -188,6 +188,23 @@
   return NULL;
 }
 
+// Iterates through the entire |list| and calls |callback| for each data element.
+// Passes the caller provided data along with node
+// If the list is empty, |callback| will never be called. It is safe to mutate the
+// list inside the callback. If an element is added before the node being visited,
+// there will be no callback for the newly-inserted node. Neither |list| nor
+// |callback| may be NULL.
+void list_foreach_ext(const list_t *list, list_iter_cb_ext callback, void *cb_data) {
+  assert(list != NULL);
+  assert(callback != NULL);
+  if (list)
+    for (list_node_t *node = list->head; node; ) {
+      list_node_t *next = node->next;
+      callback(node->data, cb_data);
+      node = next;
+    }
+}
+
 list_node_t *list_begin(const list_t *list) {
   assert(list != NULL);
   return list->head;
diff --git a/osi/src/socket.c b/osi/src/socket.c
index 4ebb3b8..abcf483 100644
--- a/osi/src/socket.c
+++ b/osi/src/socket.c
@@ -51,6 +51,11 @@
 socket_t *socket_new(void) {
   socket_t *ret = (socket_t *)osi_calloc(sizeof(socket_t));
 
+  if (ret == NULL) {
+    LOG_ERROR(LOG_TAG, "%s unable to allocate : %s", __func__, strerror(errno));
+    return NULL;
+  }
+
   ret->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   if (ret->fd == INVALID_FD) {
     LOG_ERROR(LOG_TAG, "%s unable to create socket: %s", __func__, strerror(errno));
diff --git a/osi/src/thread.c b/osi/src/thread.c
index ebeab56..c7b1eb2 100644
--- a/osi/src/thread.c
+++ b/osi/src/thread.c
@@ -66,7 +66,10 @@
   assert(work_queue_capacity != 0);
 
   thread_t *ret = osi_calloc(sizeof(thread_t));
-
+  if (ret == NULL) {
+    LOG_ERROR(LOG_TAG, "%s unable to allocate memory" , __func__);
+    return NULL;
+  }
   ret->reactor = reactor_new();
   if (!ret->reactor)
     goto error;
diff --git a/osi/src/vnd_log.c b/osi/src/vnd_log.c
new file mode 100644
index 0000000..a330f88
--- /dev/null
+++ b/osi/src/vnd_log.c
@@ -0,0 +1,89 @@
+/******************************************************************************
+Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+******************************************************************************/
+
+#define LOG_TAG "bt_vnd_log"
+
+#include <errno.h>
+#include <string.h>
+#include <dlfcn.h>
+#include "osi/include/log.h"
+#include "osi/include/osi.h"
+
+static const char *LOGGER_LIBRARY_NAME = "libbt-logClient.so";
+static const char *LOGGER_LIBRARY_SYMBOL_NAME = "BLUETOOTH_LOGGER_LIB_INTERFACE";
+
+static void *lib_handle;
+bt_logger_interface_t *logger_interface = NULL;
+bool bt_logger_enabled = false;
+
+void init_vnd_Logger(void)
+{
+  if(!bt_logger_enabled)
+  {
+    LOG_ERROR(LOG_TAG, "%s, Logger Not enabled from config file",  __func__);
+    return;
+  }
+
+  if(logger_interface)
+  {
+    LOG_ERROR(LOG_TAG, "%s, Vendor Logger is already initialized",  __func__);
+    return;
+  }
+
+  lib_handle = dlopen(LOGGER_LIBRARY_NAME, RTLD_NOW);
+
+  if (!lib_handle) {
+    LOG_ERROR(LOG_TAG, "%s unable to open %s: %s", __func__, LOGGER_LIBRARY_NAME, dlerror());
+    return;
+  }
+
+  logger_interface = (bt_logger_interface_t *)dlsym(lib_handle, LOGGER_LIBRARY_SYMBOL_NAME);
+  if (!logger_interface) {
+    LOG_ERROR(LOG_TAG, "%s unable to find symbol %s in %s: %s", __func__, LOGGER_LIBRARY_SYMBOL_NAME, LOGGER_LIBRARY_NAME, dlerror());
+    return;
+  }
+
+  logger_interface->init();
+}
+
+void clean_vnd_logger()
+{
+  if(!bt_logger_enabled)
+    return;
+
+  if(logger_interface)
+    logger_interface->cleanup();
+
+  logger_interface = NULL;
+
+  if(lib_handle)
+    dlclose(lib_handle);
+
+  lib_handle = NULL;
+}
diff --git a/service/gatt_server_old.cpp b/service/gatt_server_old.cpp
index f775be9..9c535d0 100644
--- a/service/gatt_server_old.cpp
+++ b/service/gatt_server_old.cpp
@@ -44,6 +44,8 @@
 #include "osi/include/osi.h"
 }  // extern "C"
 
+bt_logger_interface_t *logger_interface = NULL;
+
 namespace {
 
 const size_t kMaxGattAttributeSize = 512;
diff --git a/service/hal/bluetooth_interface.cpp b/service/hal/bluetooth_interface.cpp
index a551fee..d2e48ea 100644
--- a/service/hal/bluetooth_interface.cpp
+++ b/service/hal/bluetooth_interface.cpp
@@ -207,7 +207,8 @@
   ThreadEventCallback,
   nullptr, /* dut_mode_recv_cb */
   nullptr, /* le_test_mode_cb */
-  nullptr  /* energy_info_cb */
+  nullptr, /* energy_info_cb */
+  nullptr  /*hci_event_recv_cb */
 };
 
 bt_os_callouts_t bt_os_callouts = {
diff --git a/service/hal/fake_bluetooth_interface.cpp b/service/hal/fake_bluetooth_interface.cpp
index 5036c63..07de595 100644
--- a/service/hal/fake_bluetooth_interface.cpp
+++ b/service/hal/fake_bluetooth_interface.cpp
@@ -74,7 +74,9 @@
   nullptr, /* dump */
   nullptr, /* config clear */
   nullptr, /* interop_database_clear */
-  nullptr  /* interop_database_add */
+  nullptr, /* interop_database_add */
+  nullptr, /* hci_cmd_send */
+  nullptr  /* bt test app interface */
 };
 
 }  // namespace
diff --git a/stack/Android.mk b/stack/Android.mk
index 40ae5a6..8e5d7c6 100644
--- a/stack/Android.mk
+++ b/stack/Android.mk
@@ -35,9 +35,19 @@
                    $(LOCAL_PATH)/../ \
                    $(bluetooth_C_INCLUDES)
 
+ifneq ($(TARGET_SUPPORTS_WEARABLES),true)
+LOCAL_C_INCLUDES+= \
+                   vendor/qcom/opensource/bluetooth/system_bt_ext
+else
+LOCAL_C_INCLUDES+= \
+                   device/qcom/msm8909w/opensource/bluetooth/system_bt_ext
+endif
 LOCAL_SRC_FILES:= \
     ./a2dp/a2d_api.c \
     ./a2dp/a2d_sbc.c \
+    ./a2dp/a2d_aptx.c \
+    ./a2dp/a2d_aptx_hd.c \
+    ./a2dp/a2d_aac.c \
     ./avrc/avrc_api.c \
     ./avrc/avrc_sdp.c \
     ./avrc/avrc_opt.c \
@@ -153,6 +163,7 @@
 LOCAL_STATIC_LIBRARIES := libbt-hci
 LOCAL_SHARED_LIBRARIES := libcutils
 
+
 LOCAL_CFLAGS += $(bluetooth_CFLAGS)
 LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS)
 LOCAL_CPPFLAGS += $(bluetooth_CPPFLAGS)
diff --git a/stack/a2dp/a2d_aac.c b/stack/a2dp/a2d_aac.c
new file mode 100644
index 0000000..d299e00
--- /dev/null
+++ b/stack/a2dp/a2d_aac.c
@@ -0,0 +1,175 @@
+/******************************************************************************
+ *
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *   met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of The Linux Foundation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+  ******************************************************************************/
+/******************************************************************************
+ *
+ *  Utility functions to help build and parse AAC Codec Information
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include <string.h>
+#include "a2d_api.h"
+#include "a2d_int.h"
+#include "a2d_aac.h"
+#include "bt_utils.h"
+
+#if (A2D_M24_INCLUDED == TRUE)
+static UINT8 A2D_UINT32_BitsSet(UINT32 num);
+/******************************************************************************
+**
+** Function         A2D_BldAacInfo
+**
+** Description      This function builds byte sequence for
+**                  Aac Codec Capabilities.
+** Input :           media_type:  Audio or MultiMedia.
+**                  p_ie: AAC Codec Information Element
+**
+** Output :          p_result: codec info.
+**
+** Returns          A2D_SUCCESS if successful.
+**                  Error otherwise.
+******************************************************************************/
+tA2D_STATUS A2D_BldAacInfo(UINT8 media_type, tA2D_AAC_CIE *p_ie, UINT8 *p_result)
+{
+    tA2D_STATUS status;
+    if( p_ie == NULL || p_result == NULL ||
+        (p_ie->object_type & ~A2D_AAC_IE_OBJ_TYPE_MSK) ||
+        (p_ie->samp_freq & ~A2D_AAC_IE_SAMP_FREQ_MSK) ||
+        (p_ie->channels & ~A2D_AAC_IE_CHANNELS_MSK) ||
+        (p_ie->bit_rate & ~A2D_AAC_IE_BIT_RATE_MSK) ||
+        (p_ie->vbr & ~A2D_AAC_IE_VBR_MSK) )
+    {
+        /* return invalid params if invalid bit is set */
+        status = A2D_INVALID_PARAMS;
+    }
+    else
+    {
+        status = A2D_SUCCESS;
+        *p_result++ = A2D_AAC_INFO_LEN;
+        *p_result++ = media_type;
+        *p_result++ = A2D_MEDIA_CT_M24;
+
+        /* Codec information */
+        *p_result++ = p_ie->object_type; // object type
+
+        *p_result++ = (UINT8)(p_ie->samp_freq >> 8);
+
+        *p_result++ = (p_ie->samp_freq & 0x00F0)|p_ie->channels;
+        *p_result++ = p_ie->vbr | ((p_ie->bit_rate >> 16)& 0x007F);
+        *p_result++ = (p_ie->bit_rate >> 8)& 0x00FF;
+        *p_result   = p_ie->bit_rate & 0x000000FF;
+    }
+    return status;
+}
+
+/******************************************************************************
+**
+** Function         A2D_ParsAacInfo
+**
+** Description      This function parse byte sequence for
+**                  Aac Codec Capabilities.
+** Input :          p_info:  input byte sequence.
+**                  for_caps: True for getcap, false otherwise
+**
+** Output :          p_ie: Aac codec information.
+**
+** Returns          A2D_SUCCESS if successful.
+**                  Error otherwise.
+******************************************************************************/
+tA2D_STATUS A2D_ParsAacInfo(tA2D_AAC_CIE *p_ie, UINT8 *p_info, BOOLEAN for_caps)
+{
+    tA2D_STATUS status;
+    UINT8   losc;
+    UINT8   media_type;
+
+    if( p_ie == NULL || p_info == NULL)
+        status = A2D_INVALID_PARAMS;
+    else
+    {
+        losc            = *p_info++;
+        media_type      = *p_info++;
+        /* Check for wrong length, media type */
+        if(losc != A2D_AAC_INFO_LEN || *p_info != A2D_MEDIA_CT_M24)
+            status = A2D_WRONG_CODEC;
+        else
+        {
+            p_info++;
+            /* obj type */
+            p_ie->object_type = *p_info & A2D_AAC_IE_OBJ_TYPE_MSK; p_info++;
+            /* samping freq */
+            p_ie->samp_freq     = *p_info; p_info++;
+            p_ie->samp_freq = p_ie->samp_freq << 8;
+            p_ie->samp_freq |= (*p_info & 0xF0);
+            /* channels */
+            p_ie->channels = *p_info & A2D_AAC_IE_CHANNELS_MSK; p_info++;
+            /* variable bit rate */
+            p_ie->vbr =       *p_info & A2D_AAC_IE_VBR_MSK;
+            /* bit rate */
+            p_ie->bit_rate = *p_info & 0x7F;p_ie->bit_rate = p_ie->bit_rate << 8; p_info++;
+            p_ie->bit_rate |= *p_info;p_ie->bit_rate = p_ie->bit_rate << 8; p_info++;
+            p_ie->bit_rate |= *p_info;
+            status = A2D_SUCCESS;
+
+            if(for_caps == FALSE)
+            {
+                if(A2D_UINT32_BitsSet(p_ie->object_type) != A2D_SET_ONE_BIT)
+                    status = A2D_BAD_OBJ_TYPE;
+                if(A2D_UINT32_BitsSet(p_ie->samp_freq) != A2D_SET_ONE_BIT)
+                    status = A2D_BAD_SAMP_FREQ;
+                if(A2D_UINT32_BitsSet(p_ie->channels) != A2D_SET_ONE_BIT)
+                    status = A2D_BAD_CHANNEL;
+            }
+        }
+    }
+    return status;
+}
+/******************************************************************************
+** Function         A2D_UINT32_BitsSet
+**
+** Description      Check the given number of 32bit  for the number of bits set
+** Returns          A2D_SET_ONE_BIT, if one and only one bit is set
+**                  A2D_SET_ZERO_BIT, if all bits clear
+**                  A2D_SET_MULTL_BIT, if multiple bits are set
+******************************************************************************/
+static UINT8 A2D_UINT32_BitsSet(UINT32 num)
+{
+    UINT8   count;
+    BOOLEAN res;
+    if(num == 0)
+        res = A2D_SET_ZERO_BIT;
+    else
+    {
+        count = (num & (num - 1));
+        res = ((count==0)?A2D_SET_ONE_BIT:A2D_SET_MULTL_BIT);
+    }
+    return res;
+}
+#endif /* A2D_M24_INCLUDED == TRUE */
diff --git a/stack/a2dp/a2d_api.c b/stack/a2dp/a2d_api.c
index 2f31d1b..99d2104 100644
--- a/stack/a2dp/a2d_api.c
+++ b/stack/a2dp/a2d_api.c
@@ -28,6 +28,7 @@
 #include "a2d_api.h"
 #include "a2d_int.h"
 #include "avdt_api.h"
+#include "osi/include/allocator.h"
 
 /*****************************************************************************
 **  Global data
@@ -35,7 +36,16 @@
 #if A2D_DYNAMIC_MEMORY == FALSE
 tA2D_CB a2d_cb;
 #endif
-
+/* Fix for below klockwork issue.
+ * Address of a local variable is returned through formal argument 'p_db->p_attrs' in
+ * API A2D_FindService removed local declaration and defined globally renamed from a2d_attr_list
+ * to a2d_attribute_list as there is a conflict in another file avrc_sdp.c */
+UINT16 a2d_attribute_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST, /* update A2D_NUM_ATTR, if changed */
+                          ATTR_ID_BT_PROFILE_DESC_LIST,
+                          ATTR_ID_SUPPORTED_FEATURES,
+                          ATTR_ID_SERVICE_NAME,
+                          ATTR_ID_PROTOCOL_DESC_LIST,
+                          ATTR_ID_PROVIDER_NAME};
 
 /******************************************************************************
 **
@@ -272,12 +282,6 @@
 {
     tSDP_UUID   uuid_list;
     BOOLEAN     result = TRUE;
-    UINT16      a2d_attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST, /* update A2D_NUM_ATTR, if changed */
-                                   ATTR_ID_BT_PROFILE_DESC_LIST,
-                                   ATTR_ID_SUPPORTED_FEATURES,
-                                   ATTR_ID_SERVICE_NAME,
-                                   ATTR_ID_PROTOCOL_DESC_LIST,
-                                   ATTR_ID_PROVIDER_NAME};
 
     A2D_TRACE_API("A2D_FindService uuid: %x", service_uuid);
     if( (service_uuid != UUID_SERVCLASS_AUDIO_SOURCE && service_uuid != UUID_SERVCLASS_AUDIO_SINK) ||
@@ -294,7 +298,7 @@
 
     if(p_db->p_attrs == NULL || p_db->num_attr == 0)
     {
-        p_db->p_attrs  = a2d_attr_list;
+        p_db->p_attrs  = a2d_attribute_list;
         p_db->num_attr = A2D_NUM_ATTR;
     }
 
@@ -306,7 +310,7 @@
 
     if (result == TRUE)
     {
-        /* store service_uuid */
+        /* store service_uuid and discovery db pointer */
         a2d_cb.find.service_uuid = service_uuid;
         a2d_cb.find.p_cback = p_cback;
 
@@ -396,4 +400,17 @@
     a2d_cb.trace_level  = BT_TRACE_LEVEL_NONE;
 #endif
 }
+/*******************************************************************************
+**
+** Function         a2d_get_avdt_sdp_ver
+**
+** Description      This function fetches current version of AVDT.
+**
+** Returns          Current version of AVDT
+**
+*******************************************************************************/
+int a2d_get_avdt_sdp_ver ()
+{
+    return a2d_cb.avdt_sdp_ver;
+}
 
diff --git a/stack/a2dp/a2d_aptx.c b/stack/a2dp/a2d_aptx.c
new file mode 100644
index 0000000..05011bb
--- /dev/null
+++ b/stack/a2dp/a2d_aptx.c
@@ -0,0 +1,380 @@
+/******************************************************************************
+    Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are
+    met:
+        * Redistributions of source code must retain the above copyright
+          notice, this list of conditions and the following disclaimer.
+        * Redistributions in binary form must reproduce the above
+          copyright notice, this list of conditions and the following
+          disclaimer in the documentation and/or other materials provided
+          with the distribution.
+        * Neither the name of The Linux Foundation nor the names of its
+          contributors may be used to endorse or promote products derived
+          from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+    BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+    IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  Utility functions to help build and parse the aptX Codec Information
+ *  Element and Media Payload.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#include <string.h>
+#include <dlfcn.h>
+#include "osi/include/mutex.h"
+#include "osi/include/thread.h"
+#include "bt_utils.h"
+#include "a2d_api.h"
+#include "a2d_int.h"
+#include "a2d_aptx.h"
+#include "a2d_aptx_hd.h"
+#include <utils/Log.h>
+
+const char* A2D_APTX_SCHED_LIB_NAME = "libaptXScheduler.so";
+void *A2dAptXSchedLibHandle = NULL;
+thread_t *A2d_aptx_thread = NULL;
+BOOLEAN isA2dAptXEnabled = FALSE;
+
+int (*A2D_aptx_encoder_init)(void);
+A2D_AptXThreadFn (*A2D_aptx_sched_start)(void *encoder,
+                        A2D_AptXCodecType aptX_codec_type,
+                        BOOLEAN use_SCMS_T, BOOLEAN is_24bit_audio,
+                        UINT16 sample_rate, UINT8 format_bits,
+                        UINT8 channel, UINT16 MTU, A2D_AptXReadFn read_fn,
+                        A2D_AptXBufferSendFn send_fn,
+                        A2D_AptXSetPriorityFn set_priority_fn,
+                        BOOLEAN test, BOOLEAN trace);
+BOOLEAN (*A2D_aptx_sched_stop)(void);
+void (*A2D_aptx_encoder_deinit)(void);
+A2D_AptXThreadFn A2d_aptx_thread_fn;
+
+/******************************************************************************
+**
+** Function         A2D_BldAptxInfo
+**
+******************************************************************************/
+UINT8 A2D_BldAptxInfo(UINT8 media_type, tA2D_APTX_CIE *p_ie, UINT8 *p_result)
+{
+    A2D_TRACE_API("%s: - MediaType:%d", __func__, media_type);
+
+    UINT8 status = 0;
+    status = A2D_SUCCESS;
+    *p_result++ = A2D_APTX_CODEC_LEN;
+    *p_result++ = media_type;
+    *p_result++ = A2D_NON_A2DP_MEDIA_CT;
+    *p_result++ = (UINT8)(p_ie->vendorId & 0x000000FF);
+    *p_result++ = (UINT8)(p_ie->vendorId & 0x0000FF00)>> 8;
+    *p_result++ = (UINT8)(p_ie->vendorId & 0x00FF0000)>> 16;
+    *p_result++ = (UINT8)(p_ie->vendorId & 0xFF000000)>> 24;
+    *p_result++ = (UINT8)(p_ie->codecId & 0x00FF);
+    *p_result++ = (UINT8)(p_ie->codecId & 0xFF00) >> 8;
+    *p_result++ = p_ie->sampleRate | p_ie->channelMode;
+
+    return status;
+}
+
+/******************************************************************************
+**
+** Function         A2D_ParsAptxInfo
+**
+******************************************************************************/
+tA2D_STATUS A2D_ParsAptxInfo(tA2D_APTX_CIE *p_ie, UINT8 *p_info, BOOLEAN for_caps)
+{
+    tA2D_STATUS status;
+    UINT8   losc;
+    UINT8   mt;
+
+    A2D_TRACE_API("%s: - MediaType:%d", __func__, for_caps);
+
+    if (p_ie == NULL || p_info == NULL)
+    {
+        A2D_TRACE_ERROR("A2D_ParsAptxInfo - Invalid Params");
+        status = A2D_INVALID_PARAMS;
+    }
+    else
+    {
+        losc    = *p_info++;
+        mt      = *p_info++;
+        A2D_TRACE_DEBUG("%s: losc %d, mt %02x", __func__, losc, mt);
+
+        /* If the function is called for the wrong Media Type or Media Codec Type */
+        if (losc != A2D_APTX_CODEC_LEN || *p_info != A2D_NON_A2DP_MEDIA_CT) {
+            A2D_TRACE_ERROR("%s: wrong media type %02x", __func__, *p_info);
+            status = A2D_WRONG_CODEC;
+        }
+        else
+        {
+            p_info++;
+            p_ie->vendorId = (*p_info & 0x000000FF) |
+                             (*(p_info+1) << 8    & 0x0000FF00) |
+                             (*(p_info+2) << 16  & 0x00FF0000) |
+                             (*(p_info+3) << 24  & 0xFF000000);
+            p_info = p_info+4;
+            p_ie->codecId = (*p_info & 0x00FF) |(*(p_info+1) << 8 & 0xFF00);
+            p_info = p_info+2;
+            p_ie->channelMode= *p_info & 0x0F;
+            p_ie->sampleRate = *p_info & 0xF0;
+
+            status = A2D_SUCCESS;
+
+            if (for_caps == FALSE)
+            {
+                if (A2D_BitsSet(p_ie->sampleRate) != A2D_SET_ONE_BIT)
+                    status = A2D_BAD_SAMP_FREQ;
+                if (A2D_BitsSet(p_ie->channelMode) != A2D_SET_ONE_BIT)
+                    status = A2D_BAD_CH_MODE;
+            }
+        }
+    }
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         a2d_av_aptx_cfg_in_cap
+**
+** Description      This function checks whether an aptX codec configuration
+**                  is allowable for the given codec capabilities.
+**
+** Returns          0 if ok, nonzero if error.
+**
+*******************************************************************************/
+UINT8 a2d_av_aptx_cfg_in_cap(UINT8 *p_cfg, tA2D_APTX_CIE *p_cap)
+{
+    UINT8           status = 0;
+    tA2D_APTX_CIE   cfg_cie;
+
+    A2D_TRACE_API("%s", __func__);
+
+    /* parse configuration */
+    if ((status = A2D_ParsAptxInfo(&cfg_cie, p_cfg, FALSE)) != 0)
+    {
+        A2D_TRACE_ERROR("%s:, aptx parse failed", __func__);
+        return status;
+    }
+
+    /* verify that each parameter is in range */
+
+    /* sampling frequency */
+    if ((cfg_cie.sampleRate & p_cap->sampleRate) == 0)
+        status = A2D_NS_SAMP_FREQ;
+    /* channel mode */
+    else if ((cfg_cie.channelMode & p_cap->channelMode) == 0)
+        status = A2D_NS_CH_MODE;
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         A2D_check_and_init_aptX
+**
+** Description      This function checks if all the libraries required for
+**                  aptX are present and needed function pointers are resolved
+**
+** Returns          returns true if aptX codec initialization succeeds
+**
+*******************************************************************************/
+BOOLEAN A2D_check_and_init_aptX(void)
+{
+    A2D_TRACE_DEBUG("%s", __func__);
+
+    if (A2dAptXSchedLibHandle == NULL)
+    {
+        A2dAptXSchedLibHandle = dlopen(A2D_APTX_SCHED_LIB_NAME, RTLD_NOW);
+
+        if (!A2dAptXSchedLibHandle)
+        {
+            A2D_TRACE_ERROR("%s: aptX scheduler library missing", __func__);
+            goto error_exit;
+        }
+
+        A2D_aptx_encoder_init = (int (*)(void))dlsym(A2dAptXSchedLibHandle,
+                                                   "aptx_encoder_init");
+        if (!A2D_aptx_encoder_init)
+        {
+            A2D_TRACE_ERROR("%s: aptX encoder init missing", __func__);
+            goto error_exit;
+        }
+
+        A2D_aptx_sched_start = (A2D_AptXThreadFn (*)(void*, A2D_AptXCodecType, BOOLEAN,
+                                        BOOLEAN, UINT16, UINT8, UINT8, UINT16, A2D_AptXReadFn,
+                                        A2D_AptXBufferSendFn,
+                                        A2D_AptXSetPriorityFn, BOOLEAN,
+                                        BOOLEAN))dlsym(A2dAptXSchedLibHandle,
+                                        "aptx_scheduler_start");
+
+        if (!A2D_aptx_sched_start)
+        {
+            A2D_TRACE_ERROR("%s: aptX scheduler start missing", __func__);
+            goto error_exit;
+        }
+
+        A2D_aptx_sched_stop = (BOOLEAN (*)(void))dlsym(A2dAptXSchedLibHandle,
+                                                       "aptx_scheduler_stop");
+        if (!A2D_aptx_sched_stop)
+        {
+            A2D_TRACE_ERROR("%s: aptX scheduler stop missing", __func__);
+            goto error_exit;
+        }
+
+        A2D_aptx_encoder_deinit = (void (*)(void))dlsym(A2dAptXSchedLibHandle,
+                                                      "aptx_encoder_deinit");
+        if (!A2D_aptx_encoder_deinit)
+        {
+            A2D_TRACE_ERROR("%s: aptX encoder deinit missing ", __func__);
+            goto error_exit;
+        }
+
+        if (A2D_aptx_encoder_init())
+        {
+            A2D_TRACE_ERROR("%s: aptX encoder init failed - %s", __func__, dlerror());
+            goto error_exit;
+        }
+    }
+    isA2dAptXEnabled = true;
+    return isA2dAptXEnabled;
+
+ error_exit:;
+    if (A2dAptXSchedLibHandle)
+    {
+       dlclose(A2dAptXSchedLibHandle);
+       A2dAptXSchedLibHandle = NULL;
+    }
+    isA2dAptXEnabled = false;
+    return isA2dAptXEnabled;
+
+}
+
+/*******************************************************************************
+**
+** Function         A2D_start_aptX
+**
+** Description      This function Start aptX
+**
+** Returns          Nothing
+**
+*******************************************************************************/
+void A2D_start_aptX(void *encoder, A2D_AptXCodecType aptX_codec_type,
+                        BOOLEAN use_SCMS_T, BOOLEAN is_24bit_audio,
+                        UINT16 sample_rate, UINT8 format_bits,
+                        UINT8 channel, UINT16 MTU, A2D_AptXReadFn read_fn,
+                        A2D_AptXBufferSendFn send_fn,
+                        A2D_AptXSetPriorityFn set_priority_fn,
+                        BOOLEAN test, BOOLEAN trace)
+{
+    A2D_TRACE_DEBUG("%s", __func__);
+    mutex_global_lock();
+
+    A2d_aptx_thread_fn = A2D_aptx_sched_start (encoder, aptX_codec_type,
+              use_SCMS_T, is_24bit_audio, sample_rate, format_bits,
+              channel, MTU, read_fn, send_fn, set_priority_fn, test, trace);
+
+    A2d_aptx_thread = thread_new("aptx_media_worker");
+    if (A2d_aptx_thread)
+    {
+        thread_post(A2d_aptx_thread, A2d_aptx_thread_fn, NULL);
+    }
+
+    mutex_global_unlock();
+    return;
+}
+
+
+
+/*******************************************************************************
+**
+** Function         A2D_deinit_aptX
+**
+** Description      This function de-initialized aptX
+**
+** Returns          Nothing
+**
+*******************************************************************************/
+void A2D_deinit_aptX(void)
+{
+    A2D_TRACE_DEBUG("%s", __func__);
+
+    if (isA2dAptXEnabled && A2dAptXSchedLibHandle)
+    {
+        A2D_aptx_encoder_deinit();
+        isA2dAptXEnabled = false;
+    }
+
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         A2D_stop_aptX
+**
+** Description      This function remove aptX thread
+**
+** Returns          Nothing
+**
+*******************************************************************************/
+void A2D_stop_aptX(void)
+{
+    A2D_TRACE_DEBUG("%s", __func__);
+    mutex_global_lock();
+    if (A2dAptXSchedLibHandle)
+    {
+        // remove aptX thread
+        if (A2d_aptx_thread)
+        {
+            A2D_aptx_sched_stop();
+            thread_free(A2d_aptx_thread);
+            A2d_aptx_thread = NULL;
+        }
+    }
+    mutex_global_unlock();
+    return;
+}
+/*******************************************************************************
+**
+** Function         A2D_close_aptX
+**
+** Description      This function close aptX
+**
+** Returns          Nothing
+**
+*******************************************************************************/
+void A2D_close_aptX(void)
+{
+    A2D_TRACE_DEBUG("%s", __func__);
+
+    // remove aptX thread
+    A2D_stop_aptX();
+
+    // de-initialize aptX HD
+    A2D_deinit_aptX_HD();
+
+    // de-initialize aptX
+    A2D_deinit_aptX();
+
+    if (A2dAptXSchedLibHandle)
+    {
+       dlclose(A2dAptXSchedLibHandle);
+       A2dAptXSchedLibHandle = NULL;
+    }
+
+    return;
+}
diff --git a/stack/a2dp/a2d_aptx_hd.c b/stack/a2dp/a2d_aptx_hd.c
new file mode 100644
index 0000000..ee6d65e
--- /dev/null
+++ b/stack/a2dp/a2d_aptx_hd.c
@@ -0,0 +1,251 @@
+/******************************************************************************
+
+    Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are
+    met:
+        * Redistributions of source code must retain the above copyright
+          notice, this list of conditions and the following disclaimer.
+        * Redistributions in binary form must reproduce the above
+          copyright notice, this list of conditions and the following
+          disclaimer in the documentation and/or other materials provided
+          with the distribution.
+        * Neither the name of The Linux Foundation nor the names of its
+          contributors may be used to endorse or promote products derived
+          from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+    BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+    IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ******************************************************************************/
+/******************************************************************************
+
+    Utility functions to help build and parse the aptX HD Codec Information
+    Element and Media Payload.
+
+******************************************************************************/
+
+#include "bt_target.h"
+
+#include <string.h>
+#include <dlfcn.h>
+#include "osi/include/thread.h"
+#include "bt_utils.h"
+#include "a2d_api.h"
+#include "a2d_int.h"
+#include "a2d_aptx.h"
+#include "a2d_aptx_hd.h"
+#include <utils/Log.h>
+
+
+BOOLEAN isA2dAptXHdEnabled = FALSE;
+
+int (*A2D_aptx_hd_encoder_init)(void);
+void (*A2D_aptx_hd_encoder_deinit)(void);
+
+/******************************************************************************
+**
+** Function         A2D_BldAptx_hdInfo
+**
+******************************************************************************/
+UINT8 A2D_BldAptx_hdInfo(UINT8 media_type, tA2D_APTX_HD_CIE *p_ie, UINT8 *p_result)
+{
+    A2D_TRACE_API("%s: - MediaType:%d", __func__, media_type);
+
+    UINT8 status = 0;
+    status = A2D_SUCCESS;
+    *p_result++ = A2D_APTX_HD_CODEC_LEN;
+    *p_result++ = media_type;
+    *p_result++ = A2D_NON_A2DP_MEDIA_CT;
+    *p_result++ = (UINT8)(p_ie->vendorId & 0x000000FF);
+    *p_result++ = (UINT8)(p_ie->vendorId & 0x0000FF00)>> 8;
+    *p_result++ = (UINT8)(p_ie->vendorId & 0x00FF0000)>> 16;
+    *p_result++ = (UINT8)(p_ie->vendorId & 0xFF000000)>> 24;
+    *p_result++ = (UINT8)(p_ie->codecId & 0x00FF);
+    *p_result++ = (UINT8)(p_ie->codecId & 0xFF00) >> 8;
+    *p_result++ = p_ie->sampleRate | p_ie->channelMode;
+    *p_result++ = p_ie->acl_sprint_reserved0;
+    *p_result++ = p_ie->acl_sprint_reserved1;
+    *p_result++ = p_ie->acl_sprint_reserved2;
+    *p_result++ = p_ie->acl_sprint_reserved3;
+    return status;
+}
+
+/******************************************************************************
+**
+** Function         A2D_ParsAptx_hdInfo
+**
+******************************************************************************/
+tA2D_STATUS A2D_ParsAptx_hdInfo(tA2D_APTX_HD_CIE *p_ie, UINT8 *p_info, BOOLEAN for_caps)
+{
+    tA2D_STATUS status;
+    UINT8 losc;
+    UINT8 mt;
+
+    A2D_TRACE_API("%s: - MediaType:%d", __func__, for_caps);
+
+    if (p_ie == NULL || p_info == NULL)
+    {
+        A2D_TRACE_ERROR("A2D_ParsAptx_hdInfo - Invalid Params");
+        status = A2D_INVALID_PARAMS;
+    }
+    else
+    {
+        losc    = *p_info++;
+        mt      = *p_info++;
+        A2D_TRACE_DEBUG("%s: losc %d, mt %02x", __func__, losc, mt);
+
+        /* If the function is called for the wrong Media Type or Media Codec Type */
+        if (losc != A2D_APTX_HD_CODEC_LEN || *p_info != A2D_NON_A2DP_MEDIA_CT) {
+            A2D_TRACE_ERROR("%s: wrong media type %02x", __func__, *p_info);
+            status = A2D_WRONG_CODEC;
+        }
+        else
+        {
+            p_info++;
+            p_ie->vendorId = (*p_info & 0x000000FF) |
+                             (*(p_info+1) << 8   & 0x0000FF00) |
+                             (*(p_info+2) << 16  & 0x00FF0000) |
+                             (*(p_info+3) << 24  & 0xFF000000);
+            p_info = p_info+4;
+            p_ie->codecId = (*p_info & 0x00FF) | (*(p_info+1) << 8 & 0xFF00);
+            p_info = p_info+2;
+            p_ie->channelMode= *p_info & 0x0F;
+            p_ie->sampleRate = *p_info & 0xF0;
+            p_info = p_info+1;
+            p_ie->acl_sprint_reserved0 = *(p_info ++);
+            p_ie->acl_sprint_reserved1 = *(p_info ++);
+            p_ie->acl_sprint_reserved2 = *(p_info ++);
+            p_ie->acl_sprint_reserved3 = *(p_info ++);
+
+            status = A2D_SUCCESS;
+
+            if (for_caps == FALSE)
+            {
+                if (A2D_BitsSet(p_ie->sampleRate) != A2D_SET_ONE_BIT)
+                    status = A2D_BAD_SAMP_FREQ;
+                if (A2D_BitsSet(p_ie->channelMode) != A2D_SET_ONE_BIT)
+                    status = A2D_BAD_CH_MODE;
+            }
+        }
+    }
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         a2d_av_aptx_hd_cfg_in_cap
+**
+** Description      This function checks whether an aptX HD codec configuration
+**                  is allowable for the given codec capabilities.
+**
+** Returns          0 if ok, nonzero if error.
+**
+*******************************************************************************/
+UINT8 a2d_av_aptx_hd_cfg_in_cap(UINT8 *p_cfg, tA2D_APTX_HD_CIE *p_cap)
+{
+    UINT8 status = 0;
+    tA2D_APTX_HD_CIE cfg_cie;
+
+    A2D_TRACE_API("%s", __func__);
+
+    /* parse configuration */
+    if ((status = A2D_ParsAptx_hdInfo(&cfg_cie, p_cfg, FALSE)) != 0)
+    {
+        A2D_TRACE_ERROR("%s: aptX HD parse failed", __func__);
+        return status;
+    }
+
+    /* verify that each parameter is in range */
+
+    /* sampling frequency */
+    if ((cfg_cie.sampleRate & p_cap->sampleRate) == 0)
+        status = A2D_NS_SAMP_FREQ;
+    /* channel mode */
+    else if ((cfg_cie.channelMode & p_cap->channelMode) == 0)
+        status = A2D_NS_CH_MODE;
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         A2D_check_and_init_aptX_HD
+**
+** Description      This function checks if all the libraries required for
+**                  aptX HD are present and needed function pointers are resolved
+**
+** Returns          returns true if aptX HD codec initialization succeeds
+**
+*******************************************************************************/
+BOOLEAN A2D_check_and_init_aptX_HD(void)
+{
+    A2D_TRACE_DEBUG("%s", __func__);
+
+    if (isA2dAptXEnabled && A2dAptXSchedLibHandle)
+    {
+        A2D_aptx_hd_encoder_init = (int (*)(void))dlsym(A2dAptXSchedLibHandle,
+                                                   "aptx_hd_encoder_init");
+        if (!A2D_aptx_hd_encoder_init)
+        {
+            A2D_TRACE_ERROR("%s: aptX HD encoder init missing", __func__);
+            goto error_exit;
+        }
+
+        A2D_aptx_hd_encoder_deinit = (void (*)(void))dlsym(A2dAptXSchedLibHandle,
+                                                      "aptx_hd_encoder_deinit");
+        if (!A2D_aptx_hd_encoder_deinit)
+        {
+            A2D_TRACE_ERROR("%s: aptX HD encoder deinit missing", __func__);
+            goto error_exit;
+        }
+
+        if (A2D_aptx_hd_encoder_init())
+        {
+            A2D_TRACE_ERROR("%s: aptX HD encoder init failed - %s", __func__, dlerror());
+            goto error_exit;
+        }
+    } else {
+        A2D_TRACE_ERROR("%s: isA2dAptXEnabled = false", __func__);
+        goto error_exit;
+    }
+    isA2dAptXHdEnabled = true;
+    return isA2dAptXHdEnabled;
+
+ error_exit:;
+    isA2dAptXHdEnabled = false;
+    return isA2dAptXHdEnabled;
+
+}
+
+/*******************************************************************************
+**
+** Function         A2D_deinit_aptX_HD
+**
+** Description      This function de-initialized aptX HD
+**
+** Returns          Nothing
+**
+*******************************************************************************/
+void A2D_deinit_aptX_HD(void)
+{
+    A2D_TRACE_DEBUG("%s", __func__);
+
+    if (isA2dAptXHdEnabled && isA2dAptXEnabled && A2dAptXSchedLibHandle)
+    {
+       A2D_aptx_hd_encoder_deinit();
+       isA2dAptXHdEnabled = false;
+    }
+
+    return;
+}
diff --git a/stack/a2dp/a2d_int.h b/stack/a2dp/a2d_int.h
index d4bb4c2..c65127e 100644
--- a/stack/a2dp/a2d_int.h
+++ b/stack/a2dp/a2d_int.h
@@ -75,6 +75,9 @@
 /* Used only for conformance testing */
 extern void a2d_set_avdt_sdp_ver (UINT16 avdt_sdp_ver);
 
+/* Used to check local version of AVDTP */
+extern int a2d_get_avdt_sdp_ver ();
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/stack/avct/avct_api.c b/stack/avct/avct_api.c
index 60647a5..df5615d 100644
--- a/stack/avct/avct_api.c
+++ b/stack/avct/avct_api.c
@@ -38,6 +38,31 @@
 tAVCT_CB avct_cb;
 #endif
 
+
+/*******************************************************************************
+**
+** Function         AVCT_Init
+**
+** Description      This function is called to initialize the control block
+**                  for this layer.  It must be called before accessing any
+**                  other API functions for this layer.  It is typically called
+**                  once during the start up of the stack.
+**
+** Returns          void
+**
+*******************************************************************************/
+void AVCT_Init(void)
+{
+    /* initialize AVCTP data structures */
+    memset(&avct_cb, 0, sizeof(tAVCT_CB));
+
+#if defined(AVCT_INITIAL_TRACE_LEVEL)
+    avct_cb.trace_level = AVCT_INITIAL_TRACE_LEVEL;
+#else
+    avct_cb.trace_level = BT_TRACE_LEVEL_NONE;
+#endif
+}
+
 /*******************************************************************************
 **
 ** Function         AVCT_Register
@@ -80,12 +105,6 @@
     avct_cb.mtu_br = mtu_br;
 #endif
 
-#if defined(AVCT_INITIAL_TRACE_LEVEL)
-    avct_cb.trace_level = AVCT_INITIAL_TRACE_LEVEL;
-#else
-    avct_cb.trace_level = BT_TRACE_LEVEL_NONE;
-#endif
-
     if (mtu < AVCT_MIN_CONTROL_MTU)
         mtu = AVCT_MIN_CONTROL_MTU;
     /* store mtu */
@@ -112,6 +131,9 @@
 
     /* deregister PSM with L2CAP */
     L2CA_Deregister(AVCT_PSM);
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+    L2CA_Deregister(AVCT_BR_PSM);
+#endif
 }
 
 /*******************************************************************************
@@ -458,7 +480,13 @@
             else
             {
                 p_ccb->p_bcb = avct_bcb_by_lcb(p_ccb->p_lcb);
-                avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg);
+                if (p_ccb->p_bcb)
+                    avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg);
+                else
+                {
+                    result = AVCT_BAD_HANDLE;
+                    osi_free(p_msg);
+                }
             }
         }
         /* send msg event to lcb */
@@ -471,3 +499,55 @@
     return result;
 }
 
+/*******************************************************************************
+**
+** Function         AVCT_CheckIncomingConn
+**
+** Description      Check for incoming connection in progress
+**
+** Return           TRUE if incoming connection in progress, FALSE otherwise
+******************************************************************************/
+BOOLEAN AVCT_CheckIncomingConn(BD_ADDR peer_addr)
+{
+    tAVCT_LCB *p_lcb;
+
+    p_lcb = avct_lcb_by_bd(peer_addr);
+    if (p_lcb != NULL)
+    {
+        if (p_lcb->ch_state != AVCT_CH_IDLE)
+        {
+            AVCT_TRACE_ERROR("%s: Incoming AVCT connection in progress",__func__);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+/******************************************************************************
+**
+** Function         AVCT_SetTraceLevel
+**
+** Description      Sets the trace level for AVCT. If 0xff is passed, the
+**                  current trace level is returned.
+**
+**                  Input Parameters:
+**                      new_level:  The level to set the AVCT tracing to:
+**                      0xff-returns the current setting.
+**                      0-turns off tracing.
+**                      >= 1-Errors.
+**                      >= 2-Warnings.
+**                      >= 3-APIs.
+**                      >= 4-Events.
+**                      >= 5-Debug.
+**
+** Returns          The new trace level or current trace level if
+**                  the input parameter is 0xff.
+**
+******************************************************************************/
+UINT8 AVCT_SetTraceLevel (UINT8 new_level)
+{
+    if (new_level != 0xFF)
+        avct_cb.trace_level = new_level;
+
+    return (avct_cb.trace_level);
+}
+
diff --git a/stack/avct/avct_ccb.c b/stack/avct/avct_ccb.c
index e0f87de..11c45db 100644
--- a/stack/avct/avct_ccb.c
+++ b/stack/avct/avct_ccb.c
@@ -88,6 +88,7 @@
         /* control channel is down, but the browsing channel is still connected 0 disconnect it now */
         avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
         p_ccb->p_lcb = NULL;
+        memset(p_ccb, 0, sizeof(tAVCT_CCB));
     }
 #else
     memset(p_ccb, 0, sizeof(tAVCT_CCB));
@@ -148,3 +149,41 @@
     }
     return p_ccb;
 }
+
+
+/*******************************************************************************
+**
+** Function         avct_get_peer_addr_by_ccb
+**
+** Description      Return peer BD address on ccb index (or handle).
+**
+**
+** Returns          BD Address.
+**
+*******************************************************************************/
+BOOLEAN avct_get_peer_addr_by_ccb (UINT8 idx, BD_ADDR addr)
+{
+    tAVCT_CCB   *p_ccb;
+    BOOLEAN     value = FALSE;
+    p_ccb = avct_ccb_by_idx(idx);
+    if (p_ccb == NULL)
+    {
+        AVCT_TRACE_WARNING("No ccb for idx %d", idx);
+    }
+    else
+    {
+        if (p_ccb->p_lcb != NULL)
+        {
+            memcpy(addr, p_ccb->p_lcb->peer_addr, BD_ADDR_LEN);
+            value = TRUE;
+        }
+        else
+        {
+            AVCT_TRACE_WARNING("No lcb for idx %d", idx);
+        }
+    }
+    return value;
+}
+
+
+
diff --git a/stack/avct/avct_int.h b/stack/avct/avct_int.h
index 4f1705c..4f32e21 100644
--- a/stack/avct/avct_int.h
+++ b/stack/avct/avct_int.h
@@ -97,6 +97,8 @@
     UINT8               ch_flags;       /* L2CAP configuration flags */
     BT_HDR              *p_tx_msg;      /* Message to be sent - in case the browsing channel is not open when MsgReg is called */
     UINT8               ch_close;       /* CCB index+1, if CCB initiated channel close */
+    fixed_queue_t       *tx_q;          /* Transmit data buffer queue       */
+    BOOLEAN             cong;           /* TRUE, if congested */
 } tAVCT_BCB;
 
 #define AVCT_ALOC_LCB       0x01
diff --git a/stack/avct/avct_l2c.c b/stack/avct/avct_l2c.c
index ab91d7a..4ae2f65 100644
--- a/stack/avct/avct_l2c.c
+++ b/stack/avct/avct_l2c.c
@@ -35,6 +35,13 @@
 #define AVCT_L2C_CFG_IND_DONE   (1<<0)
 #define AVCT_L2C_CFG_CFM_DONE   (1<<1)
 
+/*L2CAP Browsing Parameter */
+#define AVCT_L2C_TX_WINDOW_SIZE        1
+#define AVCT_L2C_MAX_TRANSMISSION      20
+#define AVCT_L2C_RETRANS_TIMEOUT       2000
+#define AVCT_L2C_MONITOR_TIMEOUT       12000
+#define AVCT_L2C_MPS_SEGMENT_SIZE      1000
+
 /* callback function declarations */
 void avct_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
 void avct_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result);
@@ -45,6 +52,19 @@
 void avct_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested);
 void avct_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf);
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+const tL2CAP_FCR_OPTS avct_l2c_br_fcr_opts_def =
+{
+    L2CAP_FCR_ERTM_MODE,            /* Mandatory for Browsing */
+    AVCT_L2C_TX_WINDOW_SIZE,        /* Tx window size to be #define in bt_target.h*/
+    AVCT_L2C_MAX_TRANSMISSION,      /* Maximum transmissions before disconnecting */
+    AVCT_L2C_RETRANS_TIMEOUT,       /* Retransmission timeout (2 secs) */
+    AVCT_L2C_MONITOR_TIMEOUT,       /* Monitor timeout (12 secs) */
+    AVCT_L2C_MPS_SEGMENT_SIZE       /* MPS segment size */
+};
+#endif
+
+
 /* L2CAP callback function structure */
 const tL2CAP_APPL_INFO avct_l2c_appl = {
     avct_l2c_connect_ind_cback,
@@ -60,6 +80,36 @@
     NULL                                /* tL2CA_TX_COMPLETE_CB */
 };
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/* L2CAP Callback function for Browsing AVRCP 1.4 structure */
+
+/* callback function declarations */
+/* callback function declarations */
+void avct_l2c_br_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
+void avct_l2c_br_connect_cfm_cback(UINT16 lcid, UINT16 result);
+void avct_l2c_br_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
+void avct_l2c_br_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
+void avct_l2c_br_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed);
+void avct_l2c_br_disconnect_cfm_cback(UINT16 lcid, UINT16 result);
+void avct_l2c_br_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested);
+void avct_l2c_br_data_ind_cback(UINT16 lcid, BT_HDR *p_buf);
+
+
+
+const tL2CAP_APPL_INFO avct_l2c_br_appl = {
+    avct_l2c_br_connect_ind_cback,
+    avct_l2c_br_connect_cfm_cback,
+    NULL,
+    avct_l2c_br_config_ind_cback,
+    avct_l2c_br_config_cfm_cback,
+    avct_l2c_br_disconnect_ind_cback,
+    avct_l2c_br_disconnect_cfm_cback,
+    NULL,
+    avct_l2c_br_data_ind_cback,
+    avct_l2c_br_congestion_ind_cback,
+    NULL                                /* tL2CA_TX_COMPLETE_CB */
+};
+#endif
 /*******************************************************************************
 **
 ** Function         avct_l2c_is_passive
@@ -165,6 +215,113 @@
 #endif
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function       avct_l2c_br_connect_ind_cback
+**
+** Description    This is the L2CAP connect indication callback function.
+**
+** Return         void
+**
+*******************************************************************************/
+void avct_l2c_br_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
+{
+    tAVCT_BCB       *p_bcb = &avct_cb.bcb[0] ;
+    tAVCT_LCB       *p_lcb = NULL;
+    UINT16          result = L2CAP_CONN_OK;
+    tL2CAP_ERTM_INFO ertm_info;
+    tL2CAP_ERTM_INFO *p_ertm_info = NULL;
+    tL2CAP_CFG_INFO cfg;
+    UINT8 index;
+
+    AVCT_TRACE_DEBUG("avct_l2c_br_connect_ind_cback lcid:%x, psm:%x, id:%x",
+                            lcid , psm , id);
+
+    /*Check for associated lcb*/
+    if ((p_lcb = avct_lcb_by_bd(bd_addr)) == NULL)
+    {
+        AVCT_TRACE_ERROR("### LCB not found");
+        result = L2CAP_CONN_NO_RESOURCES;
+        L2CA_ErtmConnectRsp (bd_addr, id, lcid, result, L2CAP_CONN_OK, p_ertm_info);
+    }
+    else
+    {
+        /* We will only support one browsing connection.
+        * Second incoming BR conn is rejected.*/
+        for (index = 0; index < AVCT_NUM_LINKS; index++)
+        {
+            p_bcb = &avct_cb.bcb[index];
+            if (p_bcb && p_bcb->allocated)
+            {
+                AVCT_TRACE_ERROR("Browsing already connected to other device");
+                AVCT_TRACE_ERROR("Reject Browsing connection:%d", p_bcb->allocated);
+                result = L2CAP_CONN_NO_RESOURCES;
+                L2CA_ErtmConnectRsp (bd_addr, id, lcid, result, L2CAP_CONN_OK, &ertm_info);
+                return;
+            }
+        }
+        index = (UINT8) (p_lcb - &avct_cb.lcb[0]); //calculate offset.
+        AVCT_TRACE_DEBUG("index value = %d",index);
+        p_bcb   = &avct_cb.bcb[index];
+        if (p_bcb == NULL)
+        {
+            /*Disconnect as browsing channel = NULL */
+            AVCT_TRACE_ERROR("### BCB NULL");
+            result = L2CAP_CONN_NO_RESOURCES;
+            L2CA_ErtmConnectRsp (bd_addr, id, lcid, result, L2CAP_CONN_OK, &ertm_info);
+        }
+        else
+        {
+            p_bcb->allocated = index +1 ;
+            for (index = 0; index < AVCT_NUM_CONN; ++index)
+            {
+                if (avct_cb.ccb[index].p_lcb == p_lcb)
+                {
+                    AVCT_TRACE_ERROR("index value = %d",index);
+                    avct_cb.ccb[index].p_bcb = p_bcb ;
+                    avct_cb.ccb[index].allocated = AVCT_ALOC_BCB ;
+                }
+
+            }
+            AVCT_TRACE_DEBUG("Channel RSP");
+            p_bcb->ch_lcid =   lcid;     /*Updadate LCID so that on config associated bcb could be found*/
+            ertm_info.preferred_mode    = L2CAP_FCR_ERTM_MODE;
+            ertm_info.allowed_modes     = L2CAP_FCR_CHAN_OPT_ERTM;
+            ertm_info.user_rx_buf_size   = AVCT_BR_USER_RX_BUF_SIZE;
+            ertm_info.user_tx_buf_size   = AVCT_BR_USER_TX_BUF_SIZE;
+            ertm_info.fcr_rx_buf_size    = AVCT_BR_FCR_RX_BUF_SIZE;
+            ertm_info.fcr_tx_buf_size    = AVCT_BR_FCR_TX_BUF_SIZE;
+            p_ertm_info                 = &ertm_info;
+            L2CA_ErtmConnectRsp (bd_addr, id, lcid, result, L2CAP_CONN_OK, p_ertm_info);
+        }
+        /*Send L2CAP Channel Rsp if result = ok
+         * proceed with connection
+        */
+        if (result == L2CAP_CONN_OK)
+        {
+            /* transition to configuration state */
+            p_bcb->ch_state = AVCT_CH_CFG;
+            /* Send L2CAP config req */
+            memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
+            cfg.mtu_present = TRUE;
+            cfg.mtu = avct_cb.mtu_br; //As per initial config it's 1008
+            cfg.fcr_present = TRUE;
+            memcpy(&cfg.fcr, &avct_l2c_br_fcr_opts_def, sizeof (tL2CAP_FCR_OPTS));
+            /*Send Configue Request*/
+            L2CA_ConfigReq(lcid, &cfg);
+            AVCT_TRACE_DEBUG("Browse Channel mtu size = %d",cfg.mtu);
+        }
+        // Send L2CAP Config Rsp
+    }
+
+#if (BT_USE_TRACES == TRUE)
+    if (p_bcb)
+        AVCT_TRACE_DEBUG("ch_state cni: %d ", p_bcb->ch_state);
+#endif
+}
+
+#endif
 /*******************************************************************************
 **
 ** Function         avct_l2c_connect_cfm_cback
@@ -226,6 +383,21 @@
     }
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/********************************************************************************
+** Function        avct_l2c_br_connect_cfm_cback
+** Description     Function is not expected to be called
+**                 as browsing is initiated by remote device.
+**
+*********************************************************************************/
+
+void avct_l2c_br_connect_cfm_cback(UINT16 lcid, UINT16 result)
+{
+    AVCT_TRACE_ERROR("avct_l2c_br_connect_cfm_cback %x: lcid , %x: result", lcid, result );
+}
+#endif
+
+
 /*******************************************************************************
 **
 ** Function         avct_l2c_config_cfm_cback
@@ -264,7 +436,7 @@
             /* else failure */
             else
             {
-                AVCT_TRACE_DEBUG("ERROR avct_l2c_config_cfm_cback L2CA_DisconnectReq %d ", p_lcb->ch_state);
+                AVCT_TRACE_ERROR("ERROR avct_l2c_config_cfm_cback L2CA_DisconnectReq = %d ", p_lcb->ch_state);
                 /* store result value */
                 p_lcb->ch_result = p_cfg->result;
 
@@ -276,6 +448,66 @@
     }
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*************************************************************************
+** Function :            avct_l2c_br_config_cfm_cback
+**
+** Description:          This is the L2CAP config confirm callback function.
+**
+**
+** Returns               void
+**
+*************************************************************************/
+
+void avct_l2c_br_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO * p_cfg)
+{
+    tAVCT_BCB       *p_bcb;
+    AVCT_TRACE_DEBUG("avct_l2c_br_config_cfm_cback lcid : %x",lcid);
+
+    /*lookup for bcb channel, for given lcid there
+     * should be a bcb associated
+    */
+    if ((p_bcb = avct_bcb_by_lcid(lcid)) != NULL)
+    {
+        AVCT_TRACE_DEBUG("avct_l2c_br_config_cfm_cback: 0x%x, ch_state: %d, res: %d, ch_flags",
+                            lcid, p_bcb->ch_state, p_cfg->result ,p_bcb->ch_flags );
+        AVCT_TRACE_DEBUG("MTU :%x ",p_cfg->mtu);
+        /*Check for the state , it should be in config*/
+        if (p_bcb->ch_state == AVCT_CH_CFG)
+        {
+            /*Check for remote l2cap response */
+            if (p_cfg->result == L2CAP_CFG_OK)
+            {
+                /*Update BCB ch_flags ,either IND_DONE , CFM_DONE */
+                p_bcb->ch_flags |= AVCT_L2C_CFG_CFM_DONE;
+                /* Check for Configuraiton Flag , if configuration complete*/
+                if (p_bcb->ch_flags & AVCT_L2C_CFG_IND_DONE)
+                {
+                    p_bcb->ch_state = AVCT_CH_OPEN;
+                    p_bcb->state    = 0;
+                    avct_bcb_event(p_bcb, AVCT_LCB_LL_OPEN_EVT, NULL);
+                }
+            }
+            /*IF L2CAP response result is != L2CAP_CFG_OK*/
+            else
+            {
+                AVCT_TRACE_ERROR("###config_cfm_cback error, ch_state:%d ", p_bcb->ch_state);
+                /* store result value */
+                p_bcb->ch_result = p_cfg->result;
+                /* Send L2CAP disconnect req */
+                L2CA_DisconnectReq(lcid);
+            }
+        }
+        AVCT_TRACE_DEBUG("ch_state cfc: %d ", p_bcb->ch_state);
+    }
+    else
+    {
+        AVCT_TRACE_ERROR("### BCB NULL");
+        L2CA_DisconnectReq(lcid);
+    }
+}
+#endif
+
 /*******************************************************************************
 **
 ** Function         avct_l2c_config_ind_cback
@@ -324,8 +556,71 @@
         }
         AVCT_TRACE_DEBUG("ch_state cfi: %d ", p_lcb->ch_state);
     }
+    else
+    {
+        AVCT_TRACE_ERROR("%s: p_lcb is null",__func__);
+        L2CA_DisconnectReq(lcid);
+    }
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/**************************************************************************
+** Function :            avct_l2c_config_ind_cback
+**
+** Description:          This is the L2CAP config indication callback function.
+**
+**
+** Returns:              void
+**
+****************************************************************************/
+void avct_l2c_br_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
+{
+    tAVCT_BCB       *p_bcb;
+
+    AVCT_TRACE_DEBUG("config_ind_cback  tx_win_sz:%x, max_transmit:%x, rtrans:%x,mon_tout : %x",p_cfg->fcr.tx_win_sz ,\
+                       p_cfg->fcr.max_transmit , p_cfg->fcr.rtrans_tout , p_cfg->fcr.mon_tout);
+
+    if ((p_bcb = avct_bcb_by_lcid(lcid)) != NULL)
+    {
+        AVCT_TRACE_DEBUG("avct_l2c_br_config_ind_cback: 0x%x, ch_state: %d", lcid, p_bcb->ch_state);
+        /* store the mtu in tbl Start from here */
+        AVCT_TRACE_DEBUG("avct_l2c_br_config_ind_cback mtu_present: 0x%x, peer mtu: %d", p_cfg->mtu_present, p_cfg->mtu);
+        if (p_cfg->mtu_present)
+        {
+            AVCT_TRACE_DEBUG("PEER MTU: 0x%x", p_bcb->peer_mtu);
+            p_bcb->peer_mtu = p_cfg->mtu;
+        }
+        else
+        {
+            p_bcb->peer_mtu = L2CAP_DEFAULT_MTU;
+        }
+        /* send L2CAP configure response */
+        memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
+        p_cfg->result = L2CAP_CFG_OK;
+        L2CA_ConfigRsp(lcid, p_cfg);
+        /* if first config ind */
+        if ((p_bcb->ch_flags & AVCT_L2C_CFG_IND_DONE) == 0)
+        {
+            /* update flags */
+            p_bcb->ch_flags |= AVCT_L2C_CFG_IND_DONE;
+
+            /* if configuration complete */
+            if (p_bcb->ch_flags & AVCT_L2C_CFG_CFM_DONE)
+            {
+                p_bcb->ch_state = AVCT_CH_OPEN;
+                avct_bcb_event(p_bcb, AVCT_LCB_LL_OPEN_EVT, NULL);
+            }
+        }
+        AVCT_TRACE_DEBUG("ch_state cfi: %d ", p_bcb->ch_state);
+    }
+    else
+    {
+        AVCT_TRACE_ERROR("### BCB= NULL");
+        L2CA_DisconnectReq(lcid);
+    }
+}
+#endif
+
 /*******************************************************************************
 **
 ** Function         avct_l2c_disconnect_ind_cback
@@ -356,6 +651,40 @@
     }
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/********************************************************************************************
+**  Function:                       avct_l2c_br_disconnect_ind_cback
+**
+**  Description:                    This is the L2CAP disconnect indication callback function.
+**
+**
+**  Returns                        void
+**
+********************************************************************************************/
+void avct_l2c_br_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
+{
+   tAVCT_BCB       *p_bcb;
+   UINT16          result = AVCT_RESULT_FAIL;
+   AVCT_TRACE_DEBUG("avct_l2c_br_disconnect_ind_cback lcid : %d ", lcid);
+   //Lookup BCB for this event
+   if ((p_bcb = avct_bcb_by_lcid(lcid)) != NULL)
+   {
+        AVCT_TRACE_DEBUG("avct_l2c_disconnect_ind_cback: 0x%x, ch_state: %d",\
+                                lcid, p_bcb->ch_state);
+        if (ack_needed)
+        {
+            /* send L2CAP disconnect response */
+            L2CA_DisconnectRsp(lcid);
+        }
+        avct_bcb_event(p_bcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result);
+   }
+   else
+   {
+        AVCT_TRACE_ERROR("###BCB NULL");
+   }
+}
+#endif
+
 /*******************************************************************************
 **
 ** Function         avct_l2c_disconnect_cfm_cback
@@ -385,6 +714,32 @@
     }
 }
 
+
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*********************************************************************************
+**
+** Function      avct_l2c_br_disconnect_cfm_cback
+**
+** Description   This is the L2CAP disconnect Confirmation callback function
+**
+**
+** Returns       Void
+**
+***********************************************************************************/
+void avct_l2c_br_disconnect_cfm_cback(UINT16 lcid, UINT16 result)
+{
+    tAVCT_BCB      *p_bcb;
+    AVCT_TRACE_DEBUG("avct_l2c_br_disconnect_cfm_cback lcid : %d ", lcid);
+
+    if ((p_bcb = avct_bcb_by_lcid(lcid)) != NULL)
+    {
+        AVCT_TRACE_DEBUG("avct_l2c_disconnect_cfm_cback: 0x%x, ch_state: %d, res: %d",
+            lcid, p_bcb->ch_state, result);
+        p_bcb->ch_result = 0;
+    }
+}
+
+#endif
 /*******************************************************************************
 **
 ** Function         avct_l2c_congestion_ind_cback
@@ -407,6 +762,34 @@
     }
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+
+/*********************************************************************************
+** Function            avct_l2c_br_congestion_ind_cback
+**
+** Description         This is the L2CAP congestion indication callback function.
+**
+** Returns             void
+****************************************************************************/
+void avct_l2c_br_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested)
+{
+    tAVCT_BCB    *p_bcb = NULL;
+    AVCT_TRACE_DEBUG("avct_l2c_br_congestion_ind_cback lcid:%d, congestion:%d",
+                             lcid,is_congested);
+
+    /* look up for Browse Control Block for this channel */
+    p_bcb = avct_bcb_by_lcid(lcid);
+    if (p_bcb != NULL)
+    {
+        avct_bcb_event(p_bcb, AVCT_LCB_LL_CONG_EVT, (tAVCT_LCB_EVT *) &is_congested);
+    }
+    else
+    {
+        AVCT_TRACE_ERROR("### No BCB associated with lcid");
+    }
+}
+#endif
+
 /*******************************************************************************
 **
 ** Function         avct_l2c_data_ind_cback
@@ -434,3 +817,32 @@
     }
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*****************************************************************************
+**
+** Function         avct_l2c_br_data_ind_cback
+**
+** Description      This is the L2CAP data indication callback function.
+**
+** Returns          void
+**
+*****************************************************************************/
+void avct_l2c_br_data_ind_cback(UINT16 lcid, BT_HDR *p_buf)
+{
+    tAVCT_BCB       *p_bcb;
+
+    AVCT_TRACE_DEBUG("avct_l2c_br_data_ind_cback lcid : %d ", lcid);
+    AVCT_TRACE_DEBUG("BT_HDR event: %x , len: %x , offset: %x, layer_spec: %x ", p_buf->event,
+                         p_buf->len,p_buf->offset , p_buf->layer_specific );
+    if ((p_bcb = avct_bcb_by_lcid(lcid)) != NULL)
+    {
+        avct_bcb_event(p_bcb, AVCT_LCB_LL_MSG_EVT, (tAVCT_LCB_EVT *) &p_buf);
+    }
+    else /* prevent buffer leak */
+    {
+        AVCT_TRACE_WARNING("avct_l2c_br_data_ind_cback drop buffer");
+        osi_free_and_reset((void**)&p_buf);
+    }
+
+}
+#endif
diff --git a/stack/avct/avct_lcb.c b/stack/avct/avct_lcb.c
index 2f01548..364b15b 100644
--- a/stack/avct/avct_lcb.c
+++ b/stack/avct/avct_lcb.c
@@ -37,6 +37,7 @@
 
 #if BT_TRACE_VERBOSE == TRUE
 
+
 /* verbose state strings for trace */
 const char * const avct_lcb_st_str[] = {
     "LCB_IDLE_ST",
@@ -113,6 +114,27 @@
     avct_lcb_free_msg_ind
 };
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+const tAVCT_BCB_ACTION avct_bcb_action[] = {
+    avct_bcb_chnl_open,
+    avct_bcb_chnl_disc,
+    avct_bcb_send_msg,
+    avct_bcb_open_ind,
+    avct_bcb_open_fail,
+    avct_bcb_close_ind,
+    avct_bcb_close_cfm,
+    avct_bcb_msg_ind,
+    avct_bcb_cong_ind,
+    avct_bcb_bind_conn,
+    avct_bcb_bind_fail,
+    avct_bcb_unbind_disc,
+    avct_bcb_chk_disc,
+    avct_bcb_discard_msg,
+    avct_bcb_dealloc,
+    avct_bcb_free_msg_ind
+};
+#endif
+
 /* state table information */
 #define AVCT_LCB_ACTIONS            2       /* number of actions */
 #define AVCT_LCB_NEXT_STATE         2       /* position of next state */
@@ -198,9 +220,9 @@
     int                 i;
 
 #if BT_TRACE_VERBOSE == TRUE
-    AVCT_TRACE_EVENT("LCB lcb=%d event=%s state=%s", p_lcb->allocated, avct_lcb_evt_str[event], avct_lcb_st_str[p_lcb->state]);
+    BTIF_TRACE_IMP("LCB lcb=%d event=%s state=%s", p_lcb->allocated, avct_lcb_evt_str[event], avct_lcb_st_str[p_lcb->state]);
 #else
-    AVCT_TRACE_EVENT("LCB lcb=%d event=%d state=%d", p_lcb->allocated, event, p_lcb->state);
+    BTIF_TRACE_IMP("LCB lcb=%d event=%d state=%d", p_lcb->allocated, event, p_lcb->state);
 #endif
 
     /* look up the state table for the current state */
@@ -212,7 +234,7 @@
     /* execute action functions */
     for (i = 0; i < AVCT_LCB_ACTIONS; i++)
     {
-        if ((action = state_table[event][i]) != AVCT_LCB_IGNORE)
+        if ((action = state_table[event][i]) < AVCT_LCB_IGNORE)
         {
             (*avct_lcb_action[action])(p_lcb, p_data);
         }
@@ -241,9 +263,9 @@
     int                 i;
 
 #if BT_TRACE_VERBOSE == TRUE
-    AVCT_TRACE_EVENT("BCB lcb=%d event=%s state=%s", p_bcb->allocated, avct_lcb_evt_str[event], avct_lcb_st_str[p_bcb->state]);
+    BTIF_TRACE_IMP("BCB lcb=%d event=%s state=%s", p_bcb->allocated, avct_lcb_evt_str[event], avct_lcb_st_str[p_bcb->state]);
 #else
-    AVCT_TRACE_EVENT("BCB lcb=%d event=%d state=%d", p_bcb->allocated, event, p_bcb->state);
+    BTIF_TRACE_IMP("BCB lcb=%d event=%d state=%d", p_bcb->allocated, event, p_bcb->state);
 #endif
 
     /* look up the state table for the current state */
@@ -255,7 +277,7 @@
     /* execute action functions */
     for (i = 0; i < AVCT_LCB_ACTIONS; i++)
     {
-        if ((action = state_table[event][i]) != AVCT_LCB_IGNORE)
+        if ((action = state_table[event][i]) < AVCT_LCB_IGNORE)
         {
             (*avct_bcb_action[action])(p_bcb, p_data);
         }
@@ -302,6 +324,55 @@
     return p_lcb;
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*****************************************************************************
+**
+** Function         avct_bcb_by_lcb
+**
+** Description      This function finds bcb associated to a lcb
+**
+** Returns          pointer to the bcb , or NULL if none found.
+**
+*******************************************************************************/
+tAVCT_BCB *avct_bcb_by_lcb(tAVCT_LCB *p_lcb)
+{
+    int         i;
+    tAVCT_CCB   *p_ccb = &avct_cb.ccb[0];
+    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
+    {
+        AVCT_TRACE_DEBUG("avct_bcb_by_lcb %d , ccb ", p_ccb->allocated);
+        if ( p_ccb->p_lcb == p_lcb )
+        {
+            return avct_cb.ccb[i].p_bcb;
+        }
+    }
+    AVCT_TRACE_ERROR("###avct_bcb_by_lcb ERROR");
+    return NULL ;
+}
+
+/*****************************************************************************
+**
+** Function         avct_lcb_by_bcb
+**
+** Description      This
+**
+** Returns          pointer to the lcb, or NULL if none found.
+**
+*******************************************************************************/
+tAVCT_LCB *avct_lcb_by_bcb(tAVCT_BCB *p_bcb)
+{
+    tAVCT_CCB   *p_ccb = &avct_cb.ccb[0];
+    int         i;
+    for (i = 0; i < AVCT_NUM_CONN; i++)
+    {
+        AVCT_TRACE_DEBUG("avct_lcb_alloc= %d", p_bcb->allocated);
+        if(p_ccb[i].allocated && p_ccb[i].p_bcb == p_bcb)
+            return avct_cb.ccb[i].p_lcb;
+    }
+    AVCT_TRACE_ERROR("###avct_lcb_by_bcb ERROR");
+    return NULL ;
+}
+#endif
 /*******************************************************************************
 **
 ** Function         avct_lcb_alloc
@@ -374,6 +445,55 @@
     memset(p_lcb, 0, sizeof(tAVCT_LCB));
 }
 
+#if  AVCT_BROWSE_INCLUDED
+
+/*******************************************************************************
+**
+** Function         avct_bcb_dealloc
+**
+** Description      Deallocate a browse control block.
+**
+**
+** Returns          void.
+**
+*******************************************************************************/
+void avct_bcb_dealloc(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+    tAVCT_CCB   *p_ccb = &avct_cb.ccb[0];
+    BOOLEAN     found = FALSE;
+    int         i;
+
+    if (p_bcb != NULL)
+    {
+        AVCT_TRACE_DEBUG("avct_bcb_dealloc %d", p_bcb->allocated);
+        for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
+        {
+            /* if ccb allocated and */
+            if (p_ccb->allocated)
+            {
+                if (p_ccb->p_bcb == p_bcb)
+                {
+                    AVCT_TRACE_DEBUG("avct_lcb_dealloc used by ccb: %d", i);
+                    found = TRUE;
+                    break;
+                }
+            }
+        }
+
+        if (!found)
+        {
+           AVCT_TRACE_DEBUG("avct_bcb_dealloc now");
+           memset(p_bcb, 0, sizeof(tAVCT_BCB));
+        }
+    }
+    else
+    {
+        AVCT_TRACE_ERROR("### dealloc Null bcb");
+    }
+
+}
+
+#endif
 /*******************************************************************************
 **
 ** Function         avct_lcb_by_lcid
@@ -407,6 +527,41 @@
     return p_lcb;
 }
 
+#if AVCT_BROWSE_INCLUDED
+/******************************************************************************
+**
+** Function         avct_bcb_by_lcid(UINT16 lcid);
+**
+** Description      Find the BCB associated with the L2CAP LCID
+**
+** Return           pointer to browse control block
+**
+*******************************************************************************/
+
+tAVCT_BCB *avct_bcb_by_lcid(UINT16 lcid)
+{
+    AVCT_TRACE_DEBUG("avct_bcb_by_lcid :=%x",lcid);
+    tAVCT_BCB  *p_bcb = &avct_cb.bcb[0];
+    int         i;
+
+    for (i = 0; i < AVCT_NUM_LINKS; i++, p_bcb++)
+    {
+        if (p_bcb->allocated && ((p_bcb->ch_lcid == lcid)))
+        {
+            AVCT_TRACE_DEBUG("avct_bcb_by_lcid :=%x",p_bcb->ch_lcid);
+            break;
+        }
+    }
+    if (i == AVCT_NUM_LINKS)
+    {
+        /*out of bcbs */
+        p_bcb = NULL;
+        AVCT_TRACE_WARNING("###No bcb for lcid %x", lcid);
+    }
+    return p_bcb;
+}
+
+#endif
 /*******************************************************************************
 **
 ** Function         avct_lcb_has_pid
@@ -426,9 +581,11 @@
     {
         if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb) && (p_ccb->cc.pid == pid))
         {
+            AVCT_TRACE_DEBUG("avct_lcb_has_pid, found");
             return p_ccb;
         }
     }
+    AVCT_TRACE_WARNING("avct_lcb_has_pid, not found");
     return NULL;
 }
 
diff --git a/stack/avct/avct_lcb_act.c b/stack/avct/avct_lcb_act.c
index c927622..878dd82 100644
--- a/stack/avct/avct_lcb_act.c
+++ b/stack/avct/avct_lcb_act.c
@@ -168,6 +168,60 @@
     return p_ret;
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+
+/*******************************************************************************
+**
+** Function         avct_bcb_msg_asmbl
+**
+** Description      Reassemble incoming message.
+**
+**
+** Returns          Pointer to reassembled message;  NULL if no message
+**                  available.
+**
+*******************************************************************************/
+static BT_HDR *avct_bcb_msg_asmbl(tAVCT_BCB *p_bcb, BT_HDR *p_buf)
+{
+    UINT8   *p;
+    UINT8   pkt_type;
+    BT_HDR  *p_ret;
+
+    /* parse the message header */
+    AVCT_TRACE_DEBUG("bcb_msg_asmbl peer_mtu:%x, ch_lcid:%x",p_bcb->peer_mtu, \
+                              p_bcb->ch_lcid);
+    p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+    AVCT_PRS_PKT_TYPE(p, pkt_type);
+    AVCT_TRACE_DEBUG("bcb_msg_asmbl pkt_type:%d, p_buf->offset:%x",pkt_type, \
+                               p_buf->offset);
+    /* quick sanity check on length */
+    if (p_buf->len < avct_lcb_pkt_type_len[pkt_type])
+    {
+        osi_free_and_reset((void**)&p_buf);
+        AVCT_TRACE_WARNING("### Bad length during reassembly");
+        p_ret = NULL;
+    }
+
+    /* As Per AVRCP 1.5 Spec,Fragmentation is not allowed
+     * Section 7.2 AVCTP fragmentation shall not be used on the AVCTP Browsing Channel.
+     * packet type wil be single else return error
+    */
+    else if (pkt_type == AVCT_PKT_TYPE_SINGLE)
+    {
+        AVCT_TRACE_DEBUG("Got single during reassembly");
+        p_ret = p_buf;
+    }
+    else
+    {
+        osi_free_and_reset((void**)&p_buf);
+        p_ret =NULL;
+        AVCT_TRACE_WARNING("### Got Fragmented packet");
+    }
+    return p_ret;
+}
+#endif
+
+
 
 /*******************************************************************************
 **
@@ -194,6 +248,49 @@
     }
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         avct_bcb_chnl_open
+**
+** Description
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_bcb_chnl_open(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+    /*DUT does not initiate Browsing channel connect */
+    AVCT_TRACE_ERROR("###avct_bcb_chnl_open");
+}
+
+
+/********************************************************************************
+**
+** Function        avct_close_bcb
+**
+** Description     Clear BCB data structure
+**
+**
+** Returns         void.
+**
+******************************************************************************/
+void avct_close_bcb(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    tAVCT_BCB        *p_bcb = NULL;
+
+    AVCT_TRACE_DEBUG("avct_close_bcb");
+    p_bcb  = avct_bcb_by_lcb(p_lcb);
+    if (p_bcb != NULL)
+    {
+        AVCT_TRACE_DEBUG("Send Disconnect Event");
+        p_bcb->allocated = 0;
+        avct_bcb_event( p_bcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
+    }
+}
+
+#endif
+
 /*******************************************************************************
 **
 ** Function         avct_lcb_unbind_disc
@@ -211,6 +308,24 @@
     avct_ccb_dealloc(p_data->p_ccb, AVCT_DISCONNECT_CFM_EVT, 0, NULL);
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         avct_bcb_unbind_disc
+**
+** Description      Deallocate ccb and call callback with disconnect event.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_bcb_unbind_disc(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+    AVCT_TRACE_ERROR("### avct_bcb_unbind_disc");
+}
+#endif
+
+
 /*******************************************************************************
 **
 ** Function         avct_lcb_open_ind
@@ -236,8 +351,10 @@
         if (p_ccb->allocated)
         {
             /* if bound to this lcb send connect confirm event */
+            AVCT_TRACE_DEBUG("avct_lcb_open_ind, %d", p_ccb->allocated);
             if (p_ccb->p_lcb == p_lcb)
             {
+                AVCT_TRACE_DEBUG("avct_lcb_open_ind, bind true");
                 bind = TRUE;
                 L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
                 p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_CFM_EVT,
@@ -248,6 +365,7 @@
                      (avct_lcb_has_pid(p_lcb, p_ccb->cc.pid) == NULL))
             {
                 /* bind ccb to lcb and send connect ind event */
+                AVCT_TRACE_DEBUG("avct_lcb_open_ind, bind and update");
                 bind = TRUE;
                 p_ccb->p_lcb = p_lcb;
                 L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
@@ -260,10 +378,63 @@
     /* if no ccbs bound to this lcb, disconnect */
     if (bind == FALSE)
     {
+        AVCT_TRACE_DEBUG("avct_lcb_open_ind, send disconnect");
         avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
     }
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         avct_bcb_open_ind
+**
+** Description      Handle an LL_OPEN event.  For each allocated ccb already
+**                  bound to this lcb, send a connect event.  For each
+**                  unbound ccb with a new PID, bind that ccb to this lcb and
+**                  send a connect event.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_bcb_open_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+    tAVCT_CCB   *p_ccb = &avct_cb.ccb[0];
+    tAVCT_LCB   *p_lcb =NULL;
+    int         i;
+    BOOLEAN     bind = FALSE;
+
+    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
+    {
+        AVCT_TRACE_DEBUG("avct_bcb_open_ind: %d",p_ccb->allocated);
+        /*if ccb allocated */
+        if (p_ccb->allocated & AVCT_ALOC_BCB)
+        {
+            /* if bound to this bcb then send connect confirm event */
+            if (p_ccb->p_bcb == p_bcb)
+            {
+                AVCT_TRACE_DEBUG("open_ind success");
+                p_lcb   = avct_cb.ccb[i].p_lcb;
+                if (p_lcb != NULL)
+                {
+                    bind = TRUE;
+                    p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_BROWSE_CONN_CFM_EVT,
+                                          0, p_lcb->peer_addr);
+                    break;
+                }
+            }
+        }
+
+    }
+    if (bind == FALSE)
+    {
+        AVCT_TRACE_ERROR("### open_ind error");
+        avct_bcb_event(p_bcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
+    }
+}
+#endif
+
+
 /*******************************************************************************
 **
 ** Function         avct_lcb_open_fail
@@ -289,7 +460,25 @@
         }
     }
 }
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         avct_bcb_open_fail
+**
+** Description      L2CAP channel open attempt failed.  Deallocate any ccbs
+**                  on this lcb and send connect confirm event with failure.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_bcb_open_fail(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+    /* DUT does not initiate browsing channel open */
+    AVCT_TRACE_ERROR("###avct_bcb_open_fail");
+}
 
+#endif
 /*******************************************************************************
 **
 ** Function         avct_lcb_close_ind
@@ -326,6 +515,37 @@
     }
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         avct_lcb_close_ind
+**
+** Description      L2CAP channel closed by peer.  Deallocate any initiator
+**                  ccbs on this lcb and send disconnect ind event.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_bcb_close_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+    tAVCT_CCB           *p_ccb = &avct_cb.ccb[0];
+    int                 i;
+    AVCT_TRACE_DEBUG("avct_bcb_close_ind");
+    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
+    {
+        if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb))
+        {
+            //set avct_cb.bcb to 0
+            memset(p_ccb->p_bcb, 0 ,sizeof(tAVCT_BCB));
+            p_ccb->p_bcb = NULL;
+            AVCT_TRACE_DEBUG("**close_ind");
+        }
+    }
+}
+#endif
+
+
 /*******************************************************************************
 **
 ** Function         avct_lcb_close_cfm
@@ -372,6 +592,32 @@
     }
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         avct_bcb_close_cfm
+**
+** Description
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_bcb_close_cfm(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+    AVCT_TRACE_DEBUG("avct_bcb_close_cfm");
+    if (p_bcb != NULL)
+    {
+        memset(p_bcb, 0, sizeof(tAVCT_BCB));
+    }
+    else
+    {
+        AVCT_TRACE_ERROR("### avct_bcb_close_cfm");
+    }
+}
+#endif
+
+
 /*******************************************************************************
 **
 ** Function         avct_lcb_bind_conn
@@ -389,6 +635,24 @@
                                       AVCT_CONNECT_CFM_EVT, 0, p_lcb->peer_addr);
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         avct_lcb_bind_conn
+**
+** Description      Bind ccb to lcb and send connect cfm event.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_bcb_bind_conn(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+   /* DUT does not initiate browse connect*/
+   AVCT_TRACE_ERROR("###avct_bcb_bind_conn");
+}
+
+#endif
 /*******************************************************************************
 **
 ** Function         avct_lcb_chk_disc
@@ -420,6 +684,23 @@
     }
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         avct_bcb_chk_disc
+**
+** Description
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_bcb_chk_disc(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+    /* BCB disconnecton done during lcb_chk_disc */
+    AVCT_TRACE_ERROR("### avct_bcb_chk_disc");
+}
+#endif
+
 /*******************************************************************************
 **
 ** Function         avct_lcb_chnl_disc
@@ -433,10 +714,29 @@
 void avct_lcb_chnl_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
 {
     UNUSED(p_data);
-
+    AVCT_TRACE_DEBUG("avct_lcb_chnl_disc");
     L2CA_DisconnectReq(p_lcb->ch_lcid);
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         avct_bcb_chnl_disc
+**
+** Description      Disconnect L2CAP channel.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_bcb_chnl_disc(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+    AVCT_TRACE_ERROR("avct_bcb_chnl_disc");
+    /* Disconnect L2CAP Browsing channel */
+    L2CA_DisconnectReq(p_bcb->ch_lcid);
+}
+#endif
+
 /*******************************************************************************
 **
 ** Function         avct_lcb_bind_fail
@@ -455,6 +755,23 @@
     avct_ccb_dealloc(p_data->p_ccb, AVCT_CONNECT_CFM_EVT, AVCT_RESULT_FAIL, NULL);
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         avct_bcb_bind_fail
+**
+** Description
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_bcb_bind_fail(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+   /* Not expected to be called */
+   AVCT_TRACE_ERROR("###avct_bcb_bind_fail");
+}
+#endif
+
 /*******************************************************************************
 **
 ** Function         avct_lcb_cong_ind
@@ -497,6 +814,48 @@
     }
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         avct_bcb_cong_ind
+**
+** Description      Handle congestion indication from L2CAP.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_bcb_cong_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+    UINT8         event;
+    BT_HDR       *p_buf;
+
+    AVCT_TRACE_DEBUG("avct_bcb_cong_ind");
+    if (p_bcb != NULL)
+    {
+        AVCT_TRACE_DEBUG("avct_bcb_cong_ind = %d", p_data->cong);
+
+        event = (p_data->cong) ? AVCT_CONG_IND_EVT : AVCT_UNCONG_IND_EVT;
+        p_bcb->cong = p_data->cong;
+        if (p_bcb->cong == FALSE && !fixed_queue_is_empty(p_bcb->tx_q))
+        {
+            while (!p_bcb->cong &&
+                   (p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_bcb->tx_q)) != NULL)
+            {
+                if (L2CA_DataWrite(p_bcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED)
+                {
+                    p_bcb->cong = TRUE;
+                }
+            }
+        }
+    }
+    else
+    {
+        AVCT_TRACE_ERROR("### bcb NULL");
+    }
+}
+#endif
+
 /*******************************************************************************
 **
 ** Function         avct_lcb_discard_msg
@@ -515,6 +874,24 @@
     osi_free_and_reset((void **)&p_data->ul_msg.p_buf);
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         avct_bcb_discard_msg
+**
+** Description      Discard a message sent in from the API.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_bcb_discard_msg(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+    AVCT_TRACE_ERROR("### avct_bcb_discard_msg");
+    osi_free_and_reset((void**)&p_data->ul_msg.p_buf);
+}
+#endif
+
 /*******************************************************************************
 **
 ** Function         avct_lcb_send_msg
@@ -627,7 +1004,66 @@
                       fixed_queue_length(p_lcb->tx_q));
     return;
 }
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         avct_lcb_send_msg
+**
+** Description      Build and send an AVCTP message.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_bcb_send_msg(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+    UINT16          curr_msg_len;
+    UINT8           pkt_type;
+    UINT8           *p;
+    BT_HDR          *p_buf;
+    /* store msg len */
+    curr_msg_len = p_data->ul_msg.p_buf->len;
+    AVCT_TRACE_DEBUG("avct_bcb_send_msg  length: %x",curr_msg_len);
+    AVCT_TRACE_DEBUG("Remote PEER MTU: %x",p_bcb->peer_mtu);
+    /* initialize packet type and other stuff */
+    if (curr_msg_len <= (p_bcb->peer_mtu - AVCT_HDR_LEN_SINGLE))
+    {
+        pkt_type = AVCT_PKT_TYPE_SINGLE;
+        //No need to do segmentation need to send data as a single packet
+        p_buf = p_data->ul_msg.p_buf;
 
+        /* set up to build header */
+        p_buf->len += AVCT_HDR_LEN_SINGLE;
+        p_buf->offset -= AVCT_HDR_LEN_SINGLE;
+        p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+
+        /* build header */
+        p_data->ul_msg.cr = AVCT_RSP ;
+        AVCT_BLD_HDR(p, p_data->ul_msg.label, pkt_type, p_data->ul_msg.cr);
+        //UINT8_TO_STREAM(p, nosp);
+        p_data->ul_msg.p_ccb->cc.pid = 0x110E;
+        UINT16_TO_BE_STREAM(p, p_data->ul_msg.p_ccb->cc.pid);
+        if (p_bcb->cong == TRUE)
+        {
+            AVCT_TRACE_ERROR("L2CAP congestion");
+            fixed_queue_enqueue(p_bcb->tx_q, p_buf);
+        }
+        else
+        {
+            if (L2CA_DataWrite(p_bcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED)
+            {
+                AVCT_TRACE_DEBUG("L2CAP Data Write");
+                p_bcb->cong = TRUE;
+                //Flag to be cleared
+            }
+        }
+    }
+    else
+    {
+        AVCT_TRACE_ERROR("### bcb_send_msg, length incorrect");
+    }
+}
+#endif
 /*******************************************************************************
 **
 ** Function         avct_lcb_free_msg_ind
@@ -648,6 +1084,26 @@
     osi_free_and_reset((void **)&p_data->p_buf);
 }
 
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         avct_bcb_free_msg_ind
+**
+** Description      Discard an incoming AVCTP message.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_bcb_free_msg_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+    AVCT_TRACE_DEBUG("avct_bcb_free_msg_ind");
+    if (p_data)
+        osi_free_and_reset((void**)&p_data->p_buf);
+
+}
+#endif
+
 /*******************************************************************************
 **
 ** Function         avct_lcb_msg_ind
@@ -718,3 +1174,107 @@
         }
     }
 }
+
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         avct_bcb_msg_ind
+**
+** Description      Handle an incoming AVCTP message.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_bcb_msg_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
+{
+    UINT8       *p;
+    UINT8        label, type, cr_ipid;
+    UINT16       pid;
+    tAVCT_LCB   *p_lcb;
+    tAVCT_CCB   *p_ccb;
+    BT_HDR      *p_buf;
+
+    AVCT_TRACE_DEBUG("avct_bcb_msg_ind");
+    /* Update layer specific information so that while
+     * responding AVCT_MsgReq, AVCT layer knows to respond to
+     * Browsing channel
+    */
+    p_data->p_buf->layer_specific = AVCT_DATA_BROWSE;
+
+    /*
+       AVCTP fragmentation shall not be used on the AVCTP Browsing Channel
+    */
+
+    if ((p_data->p_buf = avct_bcb_msg_asmbl(p_bcb, p_data->p_buf)) == NULL)
+    {
+        AVCT_TRACE_ERROR("### Error bcb_msg_asmbl");
+        return;
+    }
+
+    /* Data passed is HCI+L2CAP+AVCT_AVRCP
+     * Point to AVCT start
+    */
+
+    p = (UINT8 *)(p_data->p_buf + 1) + p_data->p_buf->offset;
+
+    /* parse AVCT header byte */
+    AVCT_PRS_HDR(p, label, type, cr_ipid);
+
+    /* check for invalid cr_ipid */
+    if (cr_ipid == AVCT_CR_IPID_INVALID)
+    {
+        AVCT_TRACE_WARNING("### Invalid cr_ipid", cr_ipid);
+        osi_free_and_reset((void**)&p_data->p_buf);
+        return;
+    }
+    /* parse and lookup PID */
+    BE_STREAM_TO_UINT16(pid, p);
+    p_lcb = avct_lcb_by_bcb(p_bcb);
+    if (p_lcb == NULL)
+    {
+        AVCT_TRACE_ERROR("### Error lcb is NULL");
+        osi_free_and_reset((void**)&p_data->p_buf);
+    }
+    else
+    {
+        AVCT_TRACE_DEBUG("p_lcb param: p[0]: %x, p[1]: %x,\
+                  p[2] : %x, p[3] : %x ",p_lcb->peer_addr[0], p_lcb->peer_addr[1],p_lcb->peer_addr[2],\
+                  p_lcb->peer_addr[3]);
+        /* Irrespective of browsing or control
+         * message recieved is passed on to above layer
+        */
+
+        /* Check if p_lcb is correct  */
+        if ((p_ccb = avct_lcb_has_pid(p_lcb, pid)) != NULL)
+        {
+            /* PID found, send msg to upper laer, adjust
+             * bt hdr and call msg callback
+            */
+            AVCT_TRACE_DEBUG("label: %x ,cr_ipid : %d ",label, cr_ipid );
+            p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE;
+            p_data->p_buf->len    -= AVCT_HDR_LEN_SINGLE;
+            (*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid, p_data->p_buf);
+        }
+        else
+        {
+            /* PID not found; drop message */
+            AVCT_TRACE_WARNING("### No ccb for PID=%x", pid);
+            osi_free_and_reset((void**)&p_data->p_buf);
+            /* if command send reject */
+            if (cr_ipid == AVCT_CMD)
+            {
+                if ((p_buf = (BT_HDR *) osi_malloc(AVCT_CMD_BUF_SIZE)) != NULL)
+                {
+                    p_buf->len = AVCT_HDR_LEN_SINGLE;
+                    p_buf->offset = AVCT_MSG_OFFSET - AVCT_HDR_LEN_SINGLE;
+                    p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+                    AVCT_BLD_HDR(p, label, AVCT_PKT_TYPE_SINGLE, AVCT_REJ);
+                    UINT16_TO_BE_STREAM(p, pid);
+                    L2CA_DataWrite(p_lcb->ch_lcid, p_buf);
+                }
+            }
+        }
+    }
+}
+#endif
diff --git a/stack/avdt/avdt_api.c b/stack/avdt/avdt_api.c
index 5201054..50c5f90 100644
--- a/stack/avdt/avdt_api.c
+++ b/stack/avdt/avdt_api.c
@@ -39,6 +39,29 @@
 tAVDT_CB avdt_cb;
 #endif
 
+/*******************************************************************************
+**
+** Function         AVDT_Init
+**
+** Description      This function is called to initialize the control block
+**                  for this layer.  It must be called before accessing any
+**                  other API functions for this layer.  It is typically called
+**                  once during the start up of the stack.
+**
+** Returns          void
+**
+*******************************************************************************/
+void AVDT_Init(void)
+{
+    memset(&avdt_cb, 0, sizeof(tAVDT_CB));
+
+#if defined(AVDT_INITIAL_TRACE_LEVEL)
+    avdt_cb.trace_level = AVDT_INITIAL_TRACE_LEVEL;
+#else
+    avdt_cb.trace_level = BT_TRACE_LEVEL_NONE;
+#endif
+}
+
 void avdt_ccb_idle_ccb_timer_timeout(void *data)
 {
     tAVDT_CCB *p_ccb = (tAVDT_CCB *)data;
@@ -144,6 +167,40 @@
 
 /*******************************************************************************
 **
+** Function         AVDT_UpdateServiceBusyState
+**
+** Description      This function is used to set the service busy state
+**                  during outgoing connection to properly handle the
+**                  connections in upper layers.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void AVDT_UpdateServiceBusyState(BOOLEAN state)
+{
+    AVDT_TRACE_DEBUG("AVDT_UpdateServiceBusyState: %d", state);
+    avdt_cb.conn_in_progress = state;
+}
+
+/*******************************************************************************
+**
+** Function         AVDT_GetServiceBusyState
+**
+** Description      This function is used to get the service busy state
+**
+**
+** Returns          outgoing connection in progress or not
+**
+*******************************************************************************/
+BOOLEAN AVDT_GetServiceBusyState(void)
+{
+    AVDT_TRACE_DEBUG("AVDT_GetServiceBusyState: %d", avdt_cb.conn_in_progress);
+    return avdt_cb.conn_in_progress;
+}
+
+/*******************************************************************************
+**
 ** Function         AVDT_SINK_Activate
 **
 ** Description      Activate SEP of A2DP Sink. In Use parameter is adjusted.
@@ -237,16 +294,19 @@
     /* Verify parameters; if invalid, return failure */
     if (((p_cs->cfg.psc_mask & (~AVDT_PSC)) != 0) || (p_cs->p_ctrl_cback == NULL))
     {
+        AVDT_TRACE_ERROR("%s: bad param", __FUNCTION__);
         result = AVDT_BAD_PARAMS;
     }
     /* Allocate scb; if no scbs, return failure */
     else if ((p_scb = avdt_scb_alloc(p_cs)) == NULL)
     {
+        AVDT_TRACE_ERROR("%s: noresource", __FUNCTION__);
         result = AVDT_NO_RESOURCES;
     }
     else
     {
         *p_handle = avdt_scb_to_hdl(p_scb);
+        AVDT_TRACE_DEBUG("%s: allocated SCB", __FUNCTION__);
     }
     return result;
 }
@@ -1127,6 +1187,22 @@
     return (lcid);
 }
 
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+/*******************************************************************************
+**
+** Function         AVDT_GetStreamingDestChannel
+**
+** Description      Get the Dest L2CAP CID used by the stream channel.
+**
+** Returns          Destination CID.
+**
+*******************************************************************************/
+UINT16 AVDT_GetStreamingDestChannelId(UINT16 lcid)
+{
+    return L2CA_GetDestChannelID(lcid);
+}
+#endif
+
 #if AVDT_MULTIPLEXING == TRUE
 /*******************************************************************************
 **
@@ -1292,7 +1368,19 @@
     return result;
 }
 #endif
-
+/*******************************************************************************
+**
+** Function         AVDT_UpdateMaxAvClients
+**
+** Description      Update max simultaneous AV connections supported
+**
+** Returns          void
+**
+*******************************************************************************/
+void AVDT_UpdateMaxAvClients(UINT8 max_clients)
+{
+    avdt_scb_set_max_av_client(max_clients);
+}
 /******************************************************************************
 **
 ** Function         AVDT_SetTraceLevel
diff --git a/stack/avdt/avdt_ccb_act.c b/stack/avdt/avdt_ccb_act.c
index 41b74e1..8cc9bf4 100644
--- a/stack/avdt/avdt_ccb_act.c
+++ b/stack/avdt/avdt_ccb_act.c
@@ -24,6 +24,7 @@
  ******************************************************************************/
 
 #include <string.h>
+#include "btif_av_co.h"
 #include "bt_types.h"
 #include "bt_target.h"
 #include "bt_utils.h"
@@ -33,6 +34,9 @@
 #include "bt_common.h"
 #include "btu.h"
 #include "btm_api.h"
+#include "device/include/interop.h"
+#include "a2d_api.h"
+#include <hardware/bluetooth.h>
 
 extern fixed_queue_t *btu_general_alarm_queue;
 
@@ -160,15 +164,42 @@
     tAVDT_SEP_INFO      sep_info[AVDT_NUM_SEPS];
     tAVDT_SCB           *p_scb = &avdt_cb.scb[0];
     int                 i;
+    bt_bdaddr_t remote_bdaddr;
+    bdcpy(remote_bdaddr.address, p_ccb->peer_addr);
 
     p_data->msg.discover_rsp.p_sep_info = sep_info;
     p_data->msg.discover_rsp.num_seps = 0;
 
+    /* If this ccb, has done setconf and is doing discover again
+     * we should show SEP for which setconfig was done earlier
+     * This is done for IOP with some remotes */
+    for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
+    {
+        if((p_ccb != NULL)&& (p_scb->p_ccb != NULL)&&(p_scb->p_ccb == p_ccb))
+        {
+            AVDT_TRACE_EVENT(" CCB already tied to SCB[%d] ",i);
+            /* copy sep info */
+            sep_info[p_data->msg.discover_rsp.num_seps].in_use = p_scb->in_use;
+            sep_info[p_data->msg.discover_rsp.num_seps].seid = i + 1;
+            sep_info[p_data->msg.discover_rsp.num_seps].media_type = p_scb->cs.media_type;
+            sep_info[p_data->msg.discover_rsp.num_seps].tsep = p_scb->cs.tsep;
+            p_data->msg.discover_rsp.num_seps++;
+            avdt_ccb_event(p_ccb, AVDT_CCB_API_DISCOVER_RSP_EVT, p_data);
+            return;
+        }
+    }
+    p_scb = &avdt_cb.scb[0];
     /* for all allocated scbs */
     for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
     {
-        if (p_scb->allocated)
+        if ((p_scb->allocated) && (!p_scb->in_use))
         {
+            /* if the codec type is AAC and if the peer address is blacklisted */
+            if (p_scb->cs.cfg.codec_info[AVDT_CODEC_TYPE_INDEX] == A2D_MEDIA_CT_M24 &&
+                   !bta_av_co_audio_is_aac_enabled(&remote_bdaddr)) {
+                AVDT_TRACE_EVENT("%s: skipping AAC advertise\n", __func__);
+                continue;
+            }
             /* copy sep info */
             sep_info[p_data->msg.discover_rsp.num_seps].in_use = p_scb->in_use;
             sep_info[p_data->msg.discover_rsp.num_seps].seid = i + 1;
diff --git a/stack/avdt/avdt_int.h b/stack/avdt/avdt_int.h
index 1ab5f18..f356a32 100644
--- a/stack/avdt/avdt_int.h
+++ b/stack/avdt/avdt_int.h
@@ -552,6 +552,7 @@
     tAVDT_SCB_ACTION    *p_scb_act;             /* pointer to SCB action functions */
     tAVDT_CTRL_CBACK    *p_conn_cback;          /* connection callback function */
     UINT8               trace_level;            /* trace level */
+    BOOLEAN             conn_in_progress;       /* outgoing connection in progress */
 } tAVDT_CB;
 
 
@@ -615,7 +616,8 @@
 extern UINT8 avdt_scb_verify(tAVDT_CCB *p_ccb, UINT8 state, UINT8 *p_seid, UINT16 num_seid, UINT8 *p_err_code);
 extern void avdt_scb_peer_seid_list(tAVDT_MULTI *p_multi);
 extern UINT32 avdt_scb_gen_ssrc(tAVDT_SCB *p_scb);
-
+extern void avdt_scb_set_max_av_client(UINT8 num_clients);
+extern UINT8 avdt_scb_get_max_av_client(void);
 /* SCB action functions */
 extern void avdt_scb_hdl_abort_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
 extern void avdt_scb_hdl_abort_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
diff --git a/stack/avdt/avdt_l2c.c b/stack/avdt/avdt_l2c.c
index 87c7ad9..8e8b5fc 100644
--- a/stack/avdt/avdt_l2c.c
+++ b/stack/avdt/avdt_l2c.c
@@ -181,8 +181,17 @@
     tBTM_STATUS rc;
     UNUSED(psm);
 
+    /* Check if outgoing connection is in progress
+     * if yes, reject incoming connection at L2CAP
+     * level itself.
+     */
+    if(avdt_cb.conn_in_progress == TRUE)
+    {
+        AVDT_TRACE_WARNING("connect_ind: outgoing conn in progress: Reject incoming conn");
+        result = L2CAP_CONN_NO_RESOURCES;
+    }
     /* do we already have a control channel for this peer? */
-    if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
+    else if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
     {
         /* no, allocate ccb */
         if ((p_ccb = avdt_ccb_alloc(bd_addr)) == NULL)
@@ -201,11 +210,16 @@
             p_tbl->id   = id;
             p_tbl->state = AVDT_AD_ST_SEC_ACP;
             p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_ACP;
-
-            if (interop_match_addr(INTEROP_2MBPS_LINK_ONLY, (const bt_bdaddr_t *)&bd_addr)) {
+            bt_bdaddr_t remote_bdaddr;
+            bdcpy(remote_bdaddr.address, bd_addr);
+            if (interop_match_addr(INTEROP_2MBPS_LINK_ONLY, (const bt_bdaddr_t *)&remote_bdaddr)) {
                 // Disable 3DH packets for AVDT ACL to improve sensitivity on HS
                 tACL_CONN *p_acl_cb = btm_bda_to_acl(bd_addr, BT_TRANSPORT_BR_EDR);
-                btm_set_packet_types(p_acl_cb, (btm_cb.btm_acl_pkt_types_supported |
+                /* Fix for below klockwork issue
+                 * Pointer 'p_acl_cb' returned from call to function 'btm_bda_to_acl' at line 216
+                 * may be NULL and will be dereferenced at line 217*/
+                if (p_acl_cb)
+                    btm_set_packet_types(p_acl_cb, (btm_cb.btm_acl_pkt_types_supported |
                                                 HCI_PKT_TYPES_MASK_NO_3_DH1 |
                                                 HCI_PKT_TYPES_MASK_NO_3_DH3 |
                                                 HCI_PKT_TYPES_MASK_NO_3_DH5));
@@ -329,11 +343,17 @@
                         p_tbl->state = AVDT_AD_ST_SEC_INT;
                         p_tbl->lcid = lcid;
                         p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_INT;
+                        bt_bdaddr_t remote_address;
+                        bdcpy(remote_address.address, p_ccb->peer_addr);
 
-                        if (interop_match_addr(INTEROP_2MBPS_LINK_ONLY, (const bt_bdaddr_t *) &p_ccb->peer_addr)) {
+                        if (interop_match_addr(INTEROP_2MBPS_LINK_ONLY, (const bt_bdaddr_t *) &remote_address)) {
                             // Disable 3DH packets for AVDT ACL to improve sensitivity on HS
                             tACL_CONN *p_acl_cb = btm_bda_to_acl(p_ccb->peer_addr, BT_TRANSPORT_BR_EDR);
-                            btm_set_packet_types(p_acl_cb, (btm_cb.btm_acl_pkt_types_supported |
+                            /* Fix for below klockwork issue
+                             * Pointer 'p_acl_cb' returned from call to function 'btm_bda_to_acl' at line 344
+                             * may be NULL and will be dereferenced at line 345*/
+                            if (p_acl_cb)
+                                btm_set_packet_types(p_acl_cb, (btm_cb.btm_acl_pkt_types_supported |
                                                             HCI_PKT_TYPES_MASK_NO_3_DH1 |
                                                             HCI_PKT_TYPES_MASK_NO_3_DH3 |
                                                             HCI_PKT_TYPES_MASK_NO_3_DH5));
diff --git a/stack/avdt/avdt_scb.c b/stack/avdt/avdt_scb.c
index e4e7340..f02e078 100644
--- a/stack/avdt/avdt_scb.c
+++ b/stack/avdt/avdt_scb.c
@@ -511,7 +511,7 @@
     avdt_scb_st_closing
 };
 
-
+UINT8 max_av_clients = 1;
 /*******************************************************************************
 **
 ** Function         avdt_scb_event
@@ -743,13 +743,20 @@
         switch (state) {
           case AVDT_VERIFY_OPEN:
           case AVDT_VERIFY_START:
-            if (p_scb->state != AVDT_SCB_OPEN_ST && p_scb->state != AVDT_SCB_STREAM_ST)
+            /* Fix for below klockwork issue
+             * Pointer 'p_scb' checked for NULL at line 736 may be dereferenced below at line 746.
+             * need to put NULL check for p_scb */
+            if (p_scb != NULL && p_scb->state != AVDT_SCB_OPEN_ST &&
+                p_scb->state != AVDT_SCB_STREAM_ST)
               *p_err_code = AVDT_ERR_BAD_STATE;
             break;
 
           case AVDT_VERIFY_SUSPEND:
           case AVDT_VERIFY_STREAMING:
-            if (p_scb->state != AVDT_SCB_STREAM_ST)
+            /* Fix for below klockwork issue
+             * Pointer 'p_scb' checked for NULL at line 736 may be dereferenced below at line 752.
+             * need to put NULL check for p_scb */
+            if (p_scb != NULL && p_scb->state != AVDT_SCB_STREAM_ST)
               *p_err_code = AVDT_ERR_BAD_STATE;
             break;
         }
@@ -788,3 +795,31 @@
     }
 }
 
+/*******************************************************************************
+**
+** Function         avdt_scb_max_av_client
+**
+** Description      Update max simultaneous AV connections supported
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avdt_scb_set_max_av_client(UINT8 max_clients)
+{
+    max_av_clients = max_clients;
+}
+
+/*******************************************************************************
+**
+** Function         avdt_scb_get_max_av_client
+**
+** Description      Return max simultaneous AV connections supported
+**
+** Returns          max av clients supported
+**
+*******************************************************************************/
+UINT8 avdt_scb_get_max_av_client()
+{
+    return max_av_clients;
+}
+
diff --git a/stack/avdt/avdt_scb_act.c b/stack/avdt/avdt_scb_act.c
index a634ad2..0ef3ca7 100644
--- a/stack/avdt/avdt_scb_act.c
+++ b/stack/avdt/avdt_scb_act.c
@@ -1,4 +1,9 @@
 /******************************************************************************
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a contribution.
+ ******************************************************************************/
+/******************************************************************************
  *
  *  Copyright (C) 2002-2012 Broadcom Corporation
  *
@@ -65,6 +70,7 @@
     AVDT_OPEN_CFM_EVT           /* AVDT_OPEN_INT */
 };
 
+
 /*******************************************************************************
 **
 ** Function         avdt_scb_gen_ssrc
@@ -312,6 +318,7 @@
         {
             /* report sequence number */
             p_data->p_pkt->layer_specific = seq;
+            APPL_TRACE_LATENCY_AUDIO("AVDTP Recv Packet, seq number %d", seq);
             (*p_scb->cs.p_data_cback)(avdt_scb_to_hdl(p_scb), p_data->p_pkt,
                 time_stamp, (UINT8)(m_pt | (marker<<7)));
         }
@@ -864,6 +871,91 @@
                               (tAVDT_CTRL *) &p_data->msg.security_cmd);
 }
 
+void avdt_set_scbs_busy(tAVDT_SCB *ptr_scb)
+{
+    AVDT_TRACE_DEBUG(" avdt_set_scbs_busy ");
+    tAVDT_SCB       *p_scb = &avdt_cb.scb[0];
+    UINT8 reg_id = ptr_scb->cs.registration_id;
+    int i = 0;
+    for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
+    {
+        AVDT_TRACE_DEBUG(" avdt_set_scbs_busy SCB[%d] reg_id, sep_type ", i, p_scb->cs.registration_id, p_scb->cs.tsep);
+        if ((p_scb->allocated) && (p_scb->cs.registration_id == reg_id) && (p_scb->cs.tsep == ptr_scb->cs.tsep))
+        {
+            AVDT_TRACE_DEBUG(" Setting SCB[%d].in_use as true", i);
+            p_scb->in_use = TRUE;
+        }
+    }
+}
+
+void avdt_set_scbs_free(tAVDT_SCB *ptr_scb)
+{
+    AVDT_TRACE_DEBUG(" avdt_set_scbs_free ");
+    tAVDT_SCB       *p_scb = &avdt_cb.scb[0];
+    UINT8 reg_id = ptr_scb->cs.registration_id;
+    int i = 0;
+    for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
+    {
+        AVDT_TRACE_DEBUG(" avdt_set_scbs_free SCB[%d] reg_id, sep_type ", i, p_scb->cs.registration_id, p_scb->cs.tsep);
+        if ((p_scb->allocated) && (p_scb->cs.registration_id == reg_id) && (p_scb->cs.tsep == ptr_scb->cs.tsep))
+        {
+            AVDT_TRACE_DEBUG(" Setting SCB[%d].in_use as false ", i);
+            p_scb->in_use = FALSE;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avdt_check_sep_state
+**
+** Description      This function checks if either of the SEID is in use in the
+**                  cluster of a stream in which the ACP SEP for the remote
+**                  initiated connection belongs to.
+**
+** Returns          True if one SEID in the cluster is busy, False otherwise
+**
+*******************************************************************************/
+BOOLEAN avdt_check_sep_state(tAVDT_SCB *p_scb)
+{
+    int i,j;
+    int num_sep = 0,sep_offset;
+    int num_stream = avdt_scb_get_max_av_client();
+    if (num_stream == 1)
+        return false;
+    for (i = 0;i < AVDT_NUM_SEPS; i++)
+    {
+        tAVDT_SCB *temp_scb = &avdt_cb.scb[i];
+        if (p_scb == temp_scb)
+            break;
+    }
+    if (i < AVDT_NUM_SEPS)
+    {
+        sep_offset = i;
+        tAVDT_SCB *temp_scb = &avdt_cb.scb[0];
+        for (j = 0; j < AVDT_NUM_SEPS; j++, temp_scb++)
+        {
+            if (temp_scb->allocated)
+                num_sep++;
+        }
+        int num_stream  = avdt_scb_get_max_av_client();
+        int num_codecs = num_sep/num_stream;
+        for (i = 0; i < num_sep;i += num_codecs)
+        {
+            BOOLEAN in_use = false;
+            for (j = i;j < (i+num_codecs); j++)
+            {
+                tAVDT_SCB *temp_scb = &avdt_cb.scb[j];
+                if (temp_scb->in_use)
+                    in_use = true;
+            }
+            if (in_use && (sep_offset >= i && sep_offset < j))
+                return true;
+        }
+    }
+    return false;
+}
+
 /*******************************************************************************
 **
 ** Function         avdt_scb_hdl_setconfig_cmd
@@ -878,8 +970,10 @@
 void avdt_scb_hdl_setconfig_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
 {
     tAVDT_CFG *p_cfg;
+    AVDT_TRACE_WARNING("avdt_scb_hdl_setconfig_cmd: SCB in use: %d, Conn in progress: %d",
+        p_scb->in_use, avdt_cb.conn_in_progress);
 
-    if (!p_scb->in_use)
+    if ((!p_scb->in_use) && !(avdt_check_sep_state(p_scb)) && (!avdt_cb.conn_in_progress))
     {
         p_cfg = p_data->msg.config_cmd.p_cfg;
         if(p_scb->cs.cfg.codec_info[AVDT_CODEC_TYPE_INDEX] == p_cfg->codec_info[AVDT_CODEC_TYPE_INDEX])
@@ -889,6 +983,7 @@
 
             /* copy info to scb */
             p_scb->p_ccb = avdt_ccb_by_idx(p_data->msg.config_cmd.hdr.ccb_idx);
+            avdt_set_scbs_busy(p_scb);
             p_scb->peer_seid = p_data->msg.config_cmd.int_seid;
             memcpy(&p_scb->req_cfg, p_cfg, sizeof(tAVDT_CFG));
             /* call app callback */
@@ -1735,7 +1830,7 @@
     }
 #endif
     memcpy(&p_scb->req_cfg, p_data->msg.config_cmd.p_cfg, sizeof(tAVDT_CFG));
-
+    avdt_set_scbs_busy(p_scb);
     avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_SETCONFIG, &p_data->msg);
 
     /* tell ccb to open channel */
@@ -2108,6 +2203,7 @@
 void avdt_scb_clr_vars(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
 {
     UNUSED(p_data);
+    avdt_set_scbs_free(p_scb);
     p_scb->in_use = FALSE;
     p_scb->p_ccb = NULL;
     p_scb->peer_seid = 0;
diff --git a/stack/avrc/avrc_api.c b/stack/avrc/avrc_api.c
index 17c8597..d1f10ea 100644
--- a/stack/avrc/avrc_api.c
+++ b/stack/avrc/avrc_api.c
@@ -108,6 +108,29 @@
 
 /******************************************************************************
 **
+** Function         avrc_get_packet_type
+**
+** Description      Gets a packet type for fragmanted packet.
+**
+** Returns          Type of fragmenatation packet.
+**
+******************************************************************************/
+static UINT8 avrc_get_packet_type(BT_HDR *pp_pkt)
+{
+    BT_HDR      *p_pkt = pp_pkt;
+    UINT8       *p_data;
+    UINT8       pkt_type;
+    p_data  = (UINT8 *)(p_pkt+1) + p_pkt->offset;
+    /* Skip over vendor header (ctype, subunit*, opcode, CO_ID) */
+    p_data += AVRC_VENDOR_HDR_SIZE;
+
+    pkt_type = *(p_data + 1) & AVRC_PKT_TYPE_MASK;
+
+    return pkt_type;
+}
+
+/******************************************************************************
+**
 ** Function         avrc_copy_packet
 **
 ** Description      Copies an AVRC packet to a new buffer. In the new buffer,
@@ -149,7 +172,7 @@
     UINT8   *p_data, *p_orig_data;
     UINT8   rsp_type;
 
-    AVRC_TRACE_DEBUG ("avrc_prep_end_frag" );
+    AVRC_TRACE_DEBUG("avrc_prep_end_frag" );
     p_fcb = &avrc_cb.fcb[handle];
 
     /* The response type of the end fragment should be the same as the the PDU of "End Fragment
@@ -249,7 +272,7 @@
     if (pkt_type != AVRC_PKT_SINGLE)
     {
         /* reject - commands can only be in single packets at AVRCP level */
-        AVRC_TRACE_ERROR ("commands must be in single packet pdu:0x%x", *p_data );
+        AVRC_TRACE_ERROR("commands must be in single packet pdu:0x%x", *p_data );
         /* use the current GKI buffer to send the reject */
         status = AVRC_STS_BAD_CMD;
     }
@@ -363,7 +386,7 @@
     p_data += AVRC_VENDOR_HDR_SIZE;
 
     pkt_type = *(p_data + 1) & AVRC_PKT_TYPE_MASK;
-    AVRC_TRACE_DEBUG ("pkt_type %d", pkt_type );
+    AVRC_TRACE_DEBUG("pkt_type %d", pkt_type );
     p_rcb = &avrc_cb.rcb[handle];
     if (p_msg->company_id == AVRC_CO_METADATA)
     {
@@ -408,7 +431,7 @@
             } else if (p_rcb->p_rmsg == NULL) {
                 /* Received a CONTINUE/END, but no corresponding START
                               (or previous fragmented response was dropped) */
-                AVRC_TRACE_DEBUG ("Received a CONTINUE/END without no corresponding START \
+                AVRC_TRACE_DEBUG("Received a CONTINUE/END without no corresponding START \
                                    (or previous fragmented response was dropped)");
                 drop_code = 5;
                 osi_free(p_pkt);
@@ -566,136 +589,126 @@
 
     p_data  = (UINT8 *)(p_pkt+1) + p_pkt->offset;
     memset(&msg, 0, sizeof(tAVRC_MSG) );
+    /* layer_specific value use to distinguish
+     * Browsing and control channel PDU ID.
+     * AVCT_DATA_BROWSE to be used for browsing
+     * channel
+    */
+    AVRC_TRACE_DEBUG("layer_specific %x",p_pkt->layer_specific);
+    if (p_pkt->layer_specific != AVCT_DATA_BROWSE)
     {
-        if (p_pkt->len < AVRC_AVC_HDR_SIZE) {
-            android_errorWriteLog(0x534e4554, "111803925");
-            AVRC_TRACE_WARNING("%s: message length %d too short: must be at least %d",
-                               __func__, p_pkt->len, AVRC_AVC_HDR_SIZE);
-            osi_free(p_pkt);
-            return;
-        }
-        msg.hdr.ctype           = p_data[0] & AVRC_CTYPE_MASK;
-        AVRC_TRACE_DEBUG("avrc_msg_cback handle:%d, ctype:%d, offset:%d, len: %d",
-                handle, msg.hdr.ctype, p_pkt->offset, p_pkt->len);
-        msg.hdr.subunit_type    = (p_data[1] & AVRC_SUBTYPE_MASK) >> AVRC_SUBTYPE_SHIFT;
-        msg.hdr.subunit_id      = p_data[1] & AVRC_SUBID_MASK;
-        opcode                  = p_data[2];
-    }
-
-    if ( ((avrc_cb.ccb[handle].control & AVRC_CT_TARGET) && (cr == AVCT_CMD)) ||
-        ((avrc_cb.ccb[handle].control & AVRC_CT_CONTROL) && (cr == AVCT_RSP)) )
-    {
-
-        switch(opcode)
         {
-        case AVRC_OP_UNIT_INFO:
-            if (cr == AVCT_CMD)
-            {
-                /* send the response to the peer */
-                p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_UNIT_INFO_RSP_LEN);
-                p_rsp_data = avrc_get_data_ptr(p_rsp);
-                *p_rsp_data = AVRC_RSP_IMPL_STBL;
-                /* check & set the offset. set response code, set subunit_type & subunit_id,
-                   set AVRC_OP_UNIT_INFO */
-                /* 3 bytes: ctype, subunit*, opcode */
-                p_rsp_data      += AVRC_AVC_HDR_SIZE;
-                *p_rsp_data++   = 7;
-                /* Panel subunit & id=0 */
-                *p_rsp_data++   = (AVRC_SUB_PANEL << AVRC_SUBTYPE_SHIFT);
-                AVRC_CO_ID_TO_BE_STREAM(p_rsp_data, avrc_cb.ccb[handle].company_id);
-                p_rsp->len      = (UINT16) (p_rsp_data - (UINT8 *)(p_rsp + 1) - p_rsp->offset);
-                cr = AVCT_RSP;
-#if (BT_USE_TRACES == TRUE)
-                p_drop_msg = "auto respond";
-#endif
+            if (p_pkt->len < AVRC_AVC_HDR_SIZE) {
+                android_errorWriteLog(0x534e4554, "111803925");
+                AVRC_TRACE_WARNING("%s: message length %d too short: must be at least %d",
+                                   __func__, p_pkt->len, AVRC_AVC_HDR_SIZE);
+                osi_free(p_pkt);
+                return;
             }
-            else
+            msg.hdr.ctype           = p_data[0] & AVRC_CTYPE_MASK;
+            AVRC_TRACE_DEBUG("avrc_msg_cback handle:%d, ctype:%d, offset:%d, len: %d",
+                    handle, msg.hdr.ctype, p_pkt->offset, p_pkt->len);
+            msg.hdr.subunit_type    = (p_data[1] & AVRC_SUBTYPE_MASK) >> AVRC_SUBTYPE_SHIFT;
+            msg.hdr.subunit_id      = p_data[1] & AVRC_SUBID_MASK;
+            opcode                  = p_data[2];
+        }
+        AVRC_TRACE_DEBUG("opcode %d",opcode);
+        if ( ((avrc_cb.ccb[handle].control & AVRC_CT_TARGET) && (cr == AVCT_CMD)) ||
+           ((avrc_cb.ccb[handle].control & AVRC_CT_CONTROL) && (cr == AVCT_RSP)) )
+        {
+        
+            switch(opcode)
             {
-                /* parse response */
-                if (p_pkt->len < AVRC_OP_UNIT_INFO_RSP_LEN) {
-                    AVRC_TRACE_WARNING(
-                        "%s: message length %d too short: must be at least %d",
-                        __func__, p_pkt->len, AVRC_OP_UNIT_INFO_RSP_LEN);
-                    android_errorWriteLog(0x534e4554, "79883824");
-                    drop = TRUE;
-                    p_drop_msg = "UNIT_INFO_RSP too short";
-                    break;
-                }
-                p_data += 4; /* 3 bytes: ctype, subunit*, opcode + octet 3 (is 7)*/
-                msg.unit.unit_type  = (*p_data & AVRC_SUBTYPE_MASK) >> AVRC_SUBTYPE_SHIFT;
-                msg.unit.unit       = *p_data & AVRC_SUBID_MASK;
-                p_data++;
-                AVRC_BE_STREAM_TO_CO_ID(msg.unit.company_id, p_data);
-            }
-            break;
-
-        case AVRC_OP_SUB_INFO:
-            if (cr == AVCT_CMD)
-            {
-                /* send the response to the peer */
-                p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_SUB_UNIT_INFO_RSP_LEN);
-                p_rsp_data = avrc_get_data_ptr(p_rsp);
-                *p_rsp_data = AVRC_RSP_IMPL_STBL;
-                /* check & set the offset. set response code, set (subunit_type & subunit_id),
-                   set AVRC_OP_SUB_INFO, set (page & extention code) */
-                p_rsp_data      += 4;
-                /* Panel subunit & id=0 */
-                *p_rsp_data++   = (AVRC_SUB_PANEL << AVRC_SUBTYPE_SHIFT);
-                memset(p_rsp_data, AVRC_CMD_OPRND_PAD, AVRC_SUBRSP_OPRND_BYTES);
-                p_rsp_data      += AVRC_SUBRSP_OPRND_BYTES;
-                p_rsp->len      = (UINT16) (p_rsp_data - (UINT8 *)(p_rsp + 1) - p_rsp->offset);
-                cr = AVCT_RSP;
-#if (BT_USE_TRACES == TRUE)
-                p_drop_msg = "auto responded";
-#endif
-            }
-            else
-            {
-                /* parse response */
-                if (p_pkt->len < AVRC_OP_SUB_UNIT_INFO_RSP_LEN) {
-                    AVRC_TRACE_WARNING(
-                        "%s: message length %d too short: must be at least %d",
-                        __func__, p_pkt->len, AVRC_OP_SUB_UNIT_INFO_RSP_LEN);
-                    android_errorWriteLog(0x534e4554, "79883824");
-                    drop = TRUE;
-                    p_drop_msg = "SUB_UNIT_INFO_RSP too short";
-                    break;
-                }
-                p_data += AVRC_AVC_HDR_SIZE; /* 3 bytes: ctype, subunit*, opcode */
-                msg.sub.page    = (*p_data++ >> AVRC_SUB_PAGE_SHIFT) & AVRC_SUB_PAGE_MASK;
-                xx      = 0;
-                while (*p_data != AVRC_CMD_OPRND_PAD && xx<AVRC_SUB_TYPE_LEN)
-                {
-                    msg.sub.subunit_type[xx] = *p_data++ >> AVRC_SUBTYPE_SHIFT;
-                    if (msg.sub.subunit_type[xx] == AVRC_SUB_PANEL)
-                        msg.sub.panel   = TRUE;
-                    xx++;
-                }
-            }
-            break;
-
-        case AVRC_OP_VENDOR:
-            p_data  = (UINT8 *)(p_pkt+1) + p_pkt->offset;
-            p_begin = p_data;
-            if (p_pkt->len < AVRC_VENDOR_HDR_SIZE) /* 6 = ctype, subunit*, opcode & CO_ID */
-            {
+            case AVRC_OP_UNIT_INFO:
                 if (cr == AVCT_CMD)
-                    reject = TRUE;
+                {
+                    /* send the response to the peer */
+                    p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_UNIT_INFO_RSP_LEN);
+                    p_rsp_data = avrc_get_data_ptr(p_rsp);
+                    *p_rsp_data = AVRC_RSP_IMPL_STBL;
+                    /* check & set the offset. set response code, set subunit_type & subunit_id,
+                       set AVRC_OP_UNIT_INFO */
+                    /* 3 bytes: ctype, subunit*, opcode */
+                    p_rsp_data      += AVRC_AVC_HDR_SIZE;
+                    *p_rsp_data++   = 7;
+                    /* Panel subunit & id=0 */
+                    *p_rsp_data++   = (AVRC_SUB_PANEL << AVRC_SUBTYPE_SHIFT);
+                    AVRC_CO_ID_TO_BE_STREAM(p_rsp_data, avrc_cb.ccb[handle].company_id);
+                    p_rsp->len      = (UINT16) (p_rsp_data - (UINT8 *)(p_rsp + 1) - p_rsp->offset);
+                    cr = AVCT_RSP;
+#if (BT_USE_TRACES == TRUE)
+                    p_drop_msg = "auto respond";
+#endif
+                }
                 else
-                    drop = TRUE;
+                {
+                    /* parse response */
+                    if (p_pkt->len < AVRC_OP_UNIT_INFO_RSP_LEN) {
+                        AVRC_TRACE_WARNING(
+                            "%s: message length %d too short: must be at least %d",
+                            __func__, p_pkt->len, AVRC_OP_UNIT_INFO_RSP_LEN);
+                        android_errorWriteLog(0x534e4554, "79883824");
+                        drop = TRUE;
+                        p_drop_msg = "UNIT_INFO_RSP too short";
+                        break;
+                    }
+                    p_data += 4; /* 3 bytes: ctype, subunit*, opcode + octet 3 (is 7)*/
+                    msg.unit.unit_type  = (*p_data & AVRC_SUBTYPE_MASK) >> AVRC_SUBTYPE_SHIFT;
+                    msg.unit.unit       = *p_data & AVRC_SUBID_MASK;
+                    p_data++;
+                    AVRC_BE_STREAM_TO_CO_ID(msg.unit.company_id, p_data);
+                }
                 break;
-            }
-            p_data += AVRC_AVC_HDR_SIZE; /* skip the first 3 bytes: ctype, subunit*, opcode */
-            AVRC_BE_STREAM_TO_CO_ID(p_msg->company_id, p_data);
-            p_msg->p_vendor_data   = p_data;
-            p_msg->vendor_len      = p_pkt->len - (p_data - p_begin);
 
-#if (AVRC_METADATA_INCLUDED == TRUE)
-            UINT8 drop_code = 0;
-            if (p_msg->company_id == AVRC_CO_METADATA)
-            {
-                /* Validate length for metadata message */
-                if (p_pkt->len < (AVRC_VENDOR_HDR_SIZE + AVRC_MIN_META_HDR_SIZE))
+            case AVRC_OP_SUB_INFO:
+                if (cr == AVCT_CMD)
+                {
+                    /* send the response to the peer */
+                    p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_SUB_UNIT_INFO_RSP_LEN);
+                    p_rsp_data = avrc_get_data_ptr(p_rsp);
+                    *p_rsp_data = AVRC_RSP_IMPL_STBL;
+                    /* check & set the offset. set response code, set (subunit_type & subunit_id),
+                       set AVRC_OP_SUB_INFO, set (page & extention code) */
+                    p_rsp_data      += 4;
+                    /* Panel subunit & id=0 */
+                    *p_rsp_data++   = (AVRC_SUB_PANEL << AVRC_SUBTYPE_SHIFT);
+                    memset(p_rsp_data, AVRC_CMD_OPRND_PAD, AVRC_SUBRSP_OPRND_BYTES);
+                    p_rsp_data      += AVRC_SUBRSP_OPRND_BYTES;
+                    p_rsp->len      = (UINT16) (p_rsp_data - (UINT8 *)(p_rsp + 1) - p_rsp->offset);
+                    cr = AVCT_RSP;
+#if (BT_USE_TRACES == TRUE)
+                    p_drop_msg = "auto responded";
+#endif
+                }
+                else
+                {
+                    /* parse response */
+                    if (p_pkt->len < AVRC_OP_SUB_UNIT_INFO_RSP_LEN) {
+                        AVRC_TRACE_WARNING(
+                            "%s: message length %d too short: must be at least %d",
+                            __func__, p_pkt->len, AVRC_OP_SUB_UNIT_INFO_RSP_LEN);
+                        android_errorWriteLog(0x534e4554, "79883824");
+                        drop = TRUE;
+                        p_drop_msg = "SUB_UNIT_INFO_RSP too short";
+                        break;
+                    }
+                    p_data += AVRC_AVC_HDR_SIZE; /* 3 bytes: ctype, subunit*, opcode */
+                    msg.sub.page    = (*p_data++ >> AVRC_SUB_PAGE_SHIFT) & AVRC_SUB_PAGE_MASK;
+                    xx      = 0;
+                    while (*p_data != AVRC_CMD_OPRND_PAD && xx<AVRC_SUB_TYPE_LEN)
+                    {
+                        msg.sub.subunit_type[xx] = *p_data++ >> AVRC_SUBTYPE_SHIFT;
+                        if (msg.sub.subunit_type[xx] == AVRC_SUB_PANEL)
+                            msg.sub.panel   = TRUE;
+                        xx++;
+                    }
+                }
+                break;
+
+            case AVRC_OP_VENDOR:
+                p_data  = (UINT8 *)(p_pkt+1) + p_pkt->offset;
+                p_begin = p_data;
+                if (p_pkt->len <= AVRC_VENDOR_HDR_SIZE) /* 6 = ctype, subunit*, opcode & CO_ID */
                 {
                     if (cr == AVCT_CMD)
                         reject = TRUE;
@@ -703,117 +716,157 @@
                         drop = TRUE;
                     break;
                 }
+                p_data += AVRC_AVC_HDR_SIZE; /* skip the first 3 bytes: ctype, subunit*, opcode */
+                AVRC_BE_STREAM_TO_CO_ID(p_msg->company_id, p_data);
+                p_msg->p_vendor_data   = p_data;
+                p_msg->vendor_len      = p_pkt->len - (p_data - p_begin);
+                AVRC_TRACE_DEBUG(" vendor_len %d", p_msg->vendor_len);
 
-                /* Check+handle fragmented messages */
+#if (AVRC_METADATA_INCLUDED == TRUE)
+                UINT8 drop_code = 0;
+                if (p_msg->vendor_len > AVRC_META_CMD_BUF_SIZE)
+                {
+                    int packet_type = avrc_get_packet_type(p_pkt);
+                    AVRC_TRACE_DEBUG("packet_type %d", packet_type);
+                    //single packet size is greater then MTU size, reject it
+                    if (packet_type == AVRC_PKT_SINGLE)
+                    {
+                        AVRC_TRACE_ERROR("Incorrect lenght for single packet");
+                        reject = TRUE;
+                        break;
+                    }
+                }
                 drop_code = avrc_proc_far_msg(handle, label, cr, &p_pkt, p_msg);
                 if (drop_code > 0)
                     drop = TRUE;
-            }
-            if (drop_code > 0)
-            {
-                if (drop_code != 4)
-                    do_free = FALSE;
-#if (BT_USE_TRACES == TRUE)
-                switch (drop_code)
+                if (drop_code > 0)
                 {
-                case 1:
-                    p_drop_msg = "sent_frag";
-                    break;
-                case 2:
-                    p_drop_msg = "req_cont";
-                    break;
-                case 3:
-                    p_drop_msg = "sent_frag3";
-                    break;
-                case 4:
-                    p_drop_msg = "sent_frag_free";
-                    break;
-                default:
-                    p_drop_msg = "sent_fragd";
-                }
+                    if (drop_code != 4)
+                        do_free = FALSE;
+#if (BT_USE_TRACES == TRUE)
+                    switch (drop_code)
+                    {
+                    case 1:
+                        p_drop_msg = "sent_frag";
+                        break;
+                    case 2:
+                        p_drop_msg = "req_cont";
+                        break;
+                    case 3:
+                        p_drop_msg = "sent_frag3";
+                        break;
+                    case 4:
+                        p_drop_msg = "sent_frag_free";
+                        break;
+                    default:
+                        p_drop_msg = "sent_fragd";
+                    }
 #endif
-            }
+                }
 #endif /* (AVRC_METADATA_INCLUDED == TRUE) */
-            break;
+                break;
 
-        case AVRC_OP_PASS_THRU:
-            if (p_pkt->len < 5) /* 3 bytes: ctype, subunit*, opcode & op_id & len */
-            {
-                if (cr == AVCT_CMD)
-                    reject = TRUE;
+            case AVRC_OP_PASS_THRU:
+                if (p_pkt->len < 5) /* 3 bytes: ctype, subunit*, opcode & op_id & len */
+                {
+                    if (cr == AVCT_CMD)
+                        reject = TRUE;
+                    else
+                        drop = TRUE;
+                break;
+                }
+                p_data += AVRC_AVC_HDR_SIZE; /* skip the first 3 bytes: ctype, subunit*, opcode */
+                msg.pass.op_id  = (AVRC_PASS_OP_ID_MASK & *p_data);
+                if (AVRC_PASS_STATE_MASK & *p_data)
+                    msg.pass.state  = TRUE;
                 else
-                    drop = TRUE;
+                    msg.pass.state  = FALSE;
+                p_data++;
+                msg.pass.pass_len    = *p_data++;
+                if (msg.pass.pass_len != p_pkt->len - 5)
+                    msg.pass.pass_len = p_pkt->len - 5;
+                if (msg.pass.pass_len)
+                    msg.pass.p_pass_data = p_data;
+                else
+                    msg.pass.p_pass_data = NULL;
+                break;
+
+
+            default:
+                if ((avrc_cb.ccb[handle].control & AVRC_CT_TARGET) && (cr == AVCT_CMD))
+                {
+                    /* reject unsupported opcode */
+                    reject = TRUE;
+                }
+                drop    = TRUE;
                 break;
             }
-            p_data += AVRC_AVC_HDR_SIZE; /* skip the first 3 bytes: ctype, subunit*, opcode */
-            msg.pass.op_id  = (AVRC_PASS_OP_ID_MASK & *p_data);
-            if (AVRC_PASS_STATE_MASK & *p_data)
-                msg.pass.state  = TRUE;
-            else
-                msg.pass.state  = FALSE;
-            p_data++;
-            msg.pass.pass_len    = *p_data++;
-            if (msg.pass.pass_len != p_pkt->len - 5)
-                msg.pass.pass_len = p_pkt->len - 5;
-            if (msg.pass.pass_len)
-                msg.pass.p_pass_data = p_data;
-            else
-                msg.pass.p_pass_data = NULL;
-            break;
-
-
-        default:
-            if ((avrc_cb.ccb[handle].control & AVRC_CT_TARGET) && (cr == AVCT_CMD))
-            {
-                /* reject unsupported opcode */
-                reject = TRUE;
-            }
-            drop    = TRUE;
-            break;
         }
-    }
-    else /* drop the event */
-    {
+        else /* drop the event */
+        {
             drop    = TRUE;
-    }
+        }
 
-    if (reject)
-    {
-        /* reject unsupported opcode */
-        p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_REJ_MSG_LEN);
-        p_rsp_data = avrc_get_data_ptr(p_rsp);
-        *p_rsp_data = AVRC_RSP_REJ;
+        if (reject)
+        {
+            /* reject unsupported opcode */
+            p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_REJ_MSG_LEN);
+            p_rsp_data      = avrc_get_data_ptr(p_rsp);
+            *p_rsp_data     = AVRC_RSP_REJ;
 #if (BT_USE_TRACES == TRUE)
-        p_drop_msg = "rejected";
+            p_drop_msg = "rejected";
 #endif
-        cr      = AVCT_RSP;
-        drop    = TRUE;
-    }
+            cr      = AVCT_RSP;
+            drop    = TRUE;
+        }
 
-    if (p_rsp)
-    {
-        /* set to send response right away */
-        AVCT_MsgReq( handle, label, cr, p_rsp);
-        drop = TRUE;
-    }
+        if (p_rsp)
+        {
+            /* set to send response right away */
+            AVCT_MsgReq( handle, label, cr, p_rsp);
+            drop = TRUE;
+        }
 
-    if (drop == FALSE)
-    {
-        msg.hdr.opcode = opcode;
-        (*avrc_cb.ccb[handle].p_msg_cback)(handle, label, opcode, &msg);
-    }
+        if (drop == FALSE)
+        {
+            msg.hdr.opcode = opcode;
+            (*avrc_cb.ccb[handle].p_msg_cback)(handle, label, opcode, &msg);
+        }
 #if (BT_USE_TRACES == TRUE)
+        else
+        {
+            AVRC_TRACE_WARNING("avrc_msg_cback %s msg handle:%d, control:%d, cr:%d, opcode:x%x",
+                    p_drop_msg,
+                    handle, avrc_cb.ccb[handle].control, cr, opcode);
+        }
+#endif
+
+
+        if (do_free)
+            osi_free(p_pkt);
+    }
     else
     {
-        AVRC_TRACE_WARNING("avrc_msg_cback %s msg handle:%d, control:%d, cr:%d, opcode:x%x",
-                p_drop_msg,
-                handle, avrc_cb.ccb[handle].control, cr, opcode);
-    }
-#endif
-
-
-    if (do_free)
+        opcode = p_data[0];
+        AVRC_TRACE_DEBUG("opcode:%x, length:%x",opcode, p_pkt->len);
+        /*Do sanity Check here*/
+        if ((avrc_cb.ccb[handle].control & AVRC_CT_TARGET) && (cr == AVCT_CMD))
+        {
+            opcode  =  AVRC_OP_BROWSE;
+            msg.browse.browse_len = p_pkt->len;
+            AVRC_TRACE_DEBUG("Browsing length %x",msg.browse.browse_len);
+            /* Browse data remains same */
+            msg.browse.p_browse_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
+            (*avrc_cb.ccb[handle].p_msg_cback)(handle, label, opcode, &msg);
+        }
+        else
+        {
+            AVRC_TRACE_ERROR("### expect AVCT_CMD");
+        }
+        /*Free the packet as the same already got copied in BTA*/
         osi_free(p_pkt);
+    }
+
 }
 
 
@@ -933,9 +986,8 @@
         memset(&avrc_cb.rcb[*p_handle], 0, sizeof(tAVRC_RASM_CB));
 #endif
     }
-    AVRC_TRACE_DEBUG("AVRC_Open role: %d, control:%d status:%d, handle:%d", cc.role, cc.control,
-        status, *p_handle);
-
+    BTIF_TRACE_IMP(" %s AVRC_Open role: %d, control:%d status:%d, handle:%d",
+               __FUNCTION__, cc.role, cc.control, status, *p_handle);
     return status;
 }
 
@@ -1158,3 +1210,15 @@
     return AVRC_NO_RESOURCES;
 }
 
+/******************************************************************************
+**
+** Function         AVRC_CheckIncomfingConn
+**
+** Description      Check for incoming connection in progress
+**
+** Returns          TRUE if incoming ocnnection in progress, FALSE otherwise
+******************************************************************************/
+BOOLEAN AVRC_CheckIncomingConn(BD_ADDR peer_addr)
+{
+    return AVCT_CheckIncomingConn(peer_addr);
+}
diff --git a/stack/avrc/avrc_bld_ct.c b/stack/avrc/avrc_bld_ct.c
index a69f05f..b4345e7 100644
--- a/stack/avrc/avrc_bld_ct.c
+++ b/stack/avrc/avrc_bld_ct.c
@@ -199,7 +199,7 @@
     /* add length -*/
     UINT16_TO_BE_STREAM(p_data, param_len);
     UINT8_TO_BE_STREAM(p_data,num_attrib_id);
-    for(int count = 0; count < num_attrib_id; count ++)
+    for(int count = 0; count < num_attrib_id && count < AVRC_MAX_APP_ATTR_SIZE; count ++)
     {
         UINT8_TO_BE_STREAM(p_data,attrib_ids[count]);
     }
@@ -321,7 +321,7 @@
     UINT32_TO_BE_STREAM(p_data,0);
     UINT32_TO_BE_STREAM(p_data,0);
     UINT8_TO_BE_STREAM(p_data,num_attrib);
-    for(int count = 0; count < num_attrib; count ++)
+    for(int count = 0; count < num_attrib && count < AVRC_MAX_ELEM_ATTR_SIZE; count ++)
     {
         UINT32_TO_BE_STREAM(p_data,attrib_ids[count]);
     }
@@ -473,6 +473,10 @@
         status = avrc_bld_list_player_app_values_cmd(p_pkt,p_cmd->list_app_values.attr_id);
         break;
     case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
+        /* Fix for below Klockwork Issue,taken care in the function
+         * defination avrc_bld_get_current_player_app_values_cmd()
+         * Array 'p_cmd->get_cur_app_val.attrs' of
+         * size 8 may use index value(s) 16..254*/
         status = avrc_bld_get_current_player_app_values_cmd(p_pkt,
              p_cmd->get_cur_app_val.num_attr,p_cmd->get_cur_app_val.attrs);
         break;
@@ -487,6 +491,10 @@
         avrc_bld_get_player_app_setting_value_text_cmd(p_pkt, &p_cmd->get_app_val_txt);
         break;
     case AVRC_PDU_GET_ELEMENT_ATTR:
+        /* Fix for below Klockwork Issue,taken care in the function
+         * defination avrc_bld_get_element_attr_cmd()
+         * Array 'p_cmd->get_elem_attrs.attrs' of
+         * size 8 may use index value(s) 8..254*/
         status = avrc_bld_get_element_attr_cmd(p_pkt,
               p_cmd->get_elem_attrs.num_attr,p_cmd->get_elem_attrs.attrs);
         break;
diff --git a/stack/avrc/avrc_bld_tg.c b/stack/avrc/avrc_bld_tg.c
index 129b386..5c184e7 100644
--- a/stack/avrc/avrc_bld_tg.c
+++ b/stack/avrc/avrc_bld_tg.c
@@ -28,6 +28,10 @@
 *****************************************************************************/
 #if (AVRC_METADATA_INCLUDED == TRUE)
 
+#define EVT_AVAIL_PLAYER_CHANGE_RSP_LENGTH 1
+#define EVT_ADDR_PLAYER_CHANGE_RSP_LENGTH 5
+#define EVT_NOW_PLAYING_CHANGE_RSP_LENGTH 1
+
 /*******************************************************************************
 **
 ** Function         avrc_bld_get_capability_rsp
@@ -645,11 +649,23 @@
             status = AVRC_STS_BAD_PARAM;
         break;
 
+    case AVRC_EVT_AVAL_PLAYERS_CHANGE:
+        len = EVT_AVAIL_PLAYER_CHANGE_RSP_LENGTH;
+        break;
+
+    case AVRC_EVT_ADDR_PLAYER_CHANGE:
+        UINT16_TO_BE_STREAM(p_data,p_rsp->param.addr_player.player_id);
+        UINT16_TO_BE_STREAM(p_data,p_rsp->param.addr_player.uid_counter);
+        len = EVT_ADDR_PLAYER_CHANGE_RSP_LENGTH;
+        break;
+
+    case AVRC_EVT_NOW_PLAYING_CHANGE:
+        len = EVT_NOW_PLAYING_CHANGE_RSP_LENGTH;
+        break;
     case AVRC_EVT_VOLUME_CHANGE:
         len = 2;
         UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_rsp->param.volume));
         break;
-
     default:
         status = AVRC_STS_BAD_PARAM;
         AVRC_TRACE_ERROR("%s unknown event_id", __func__);
@@ -748,6 +764,7 @@
     return AVRC_STS_NO_ERROR;
 }
 
+
 /*******************************************************************************
 **
 ** Function         avrc_bld_group_navigation_rsp
@@ -773,6 +790,282 @@
     return AVRC_STS_NO_ERROR;
 }
 
+/*****************************************************************************
+**
+** Function           avrc_bld_folder_item_values_rsp
+**
+** Description        This function builds the folder item response.
+**
+** Returns            AVRC_STS_NO_ERROR,if the response is built successfully
+**                    otherwise error code
+**
+******************************************************************************/
+static tAVRC_STS  avrc_bld_folder_item_values_rsp(tAVRC_GET_ITEMS_RSP *p_rsp, BT_HDR *p_pkt )
+{
+    UINT8 *p_data, *p_start, *p_length, *p_media_element_len;
+    UINT16 itemlength, param_length;
+    UINT16 item_numb = 0, i, xx, media_attr_count;
+
+    AVRC_TRACE_DEBUG(" avrc_bld_folder_item_values_rsp offset :x%x", p_pkt->offset);
+    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+    /* As per AVRCP spec, first byte of response is PDU ID
+     * and Response does not have any opcode
+    */
+    p_data = p_start;
+    /*First OCT carry PDU information */
+    *p_data++ = p_rsp->pdu;
+
+    /* Refer Media Play list AVRCP 1.5 22.19 (Get Folder Items)
+     * Mark a pointer to be filled once length is calculated at last
+    */
+    p_length = p_data;
+
+    /*increment to adjust length*/
+    p_data = p_data + 2;
+    /*Status is checked in Btif layer*/
+    *p_data++ = p_rsp->status;
+    if(p_rsp->status != AVRC_STS_NO_ERROR)
+    {
+        //TODO Response
+        AVRC_TRACE_ERROR(" ### Folder_item_values response error");
+        return p_rsp->status;
+    }
+    /*UID Counter OCT 4 and 5*/
+    UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter);
+    /*Number of Items OCT 6 and 7*/
+    item_numb = p_rsp->item_count;
+    UINT16_TO_BE_STREAM(p_data, p_rsp->item_count);
+    param_length = 0;
+    for (i = 0; i < item_numb; i++)
+    {
+        itemlength = 0;
+        switch(p_rsp->p_item_list[i].item_type)
+        {
+            case AVRC_ITEM_PLAYER:
+                UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].item_type);
+                itemlength = 28 + p_rsp->p_item_list[i].u.player.name.str_len;
+                UINT16_TO_BE_STREAM(p_data, itemlength);
+                UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.player_id);
+                UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.major_type);
+                UINT32_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.sub_type);
+                UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.play_status);
+                ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.features,\
+                                                                AVRC_FEATURE_MASK_SIZE);
+                UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.name.charset_id);
+                UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.name.str_len);
+                ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.name.p_str,\
+                                   p_rsp->p_item_list[i].u.player.name.str_len);
+                break;
+            case AVRC_ITEM_FOLDER:
+                UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].item_type);
+                itemlength = 14 + p_rsp->p_item_list[i].u.folder.name.str_len;
+                UINT16_TO_BE_STREAM(p_data, itemlength);
+                ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.uid ,AVRC_UID_SIZE);
+                UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.type);
+                UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.playable);
+                UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.name.charset_id);
+                UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.name.str_len);
+                ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.name.p_str,\
+                                   p_rsp->p_item_list[i].u.folder.name.str_len);
+                break;
+            case AVRC_ITEM_MEDIA:
+                UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].item_type);
+                p_media_element_len = p_data;
+                itemlength = 13 + p_rsp->p_item_list[i].u.media.name.str_len;
+                p_data = p_data + 2; /* for length */
+                ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.uid ,AVRC_UID_SIZE);
+                UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.type);
+                UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.name.charset_id);
+                UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.name.str_len);
+                ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.name.p_str,\
+                                                   p_rsp->p_item_list[i].u.media.name.str_len);
+                UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.attr_count);
+                media_attr_count = p_rsp->p_item_list[i].u.media.attr_count;
+                itemlength += 1; /* for attribute count  */
+                for (xx = 0; xx < media_attr_count; xx++)
+                {
+                    itemlength += 8 +  p_rsp->p_item_list[i].u.media.p_attr_list[xx].name.str_len;
+                    UINT32_TO_BE_STREAM(p_data,\
+                        p_rsp->p_item_list[i].u.media.p_attr_list[xx].attr_id);
+                    UINT16_TO_BE_STREAM(p_data,\
+                        p_rsp->p_item_list[i].u.media.p_attr_list[xx].name.charset_id);
+                    UINT16_TO_BE_STREAM(p_data,\
+                        p_rsp->p_item_list[i].u.media.p_attr_list[xx].name.str_len);
+                    ARRAY_TO_BE_STREAM(p_data,\
+                        p_rsp->p_item_list[i].u.media.p_attr_list[xx].name.p_str,\
+                        p_rsp->p_item_list[i].u.media.p_attr_list[xx].name.str_len);
+                }
+                UINT16_TO_BE_STREAM(p_media_element_len, itemlength);
+                break;
+        }
+        param_length += itemlength + 3; /* 3 to accommodate item_len and item_type */
+    }
+    param_length = param_length + 5; //Add explicit 5, 2 num items+ 2UID Counter + 1 status counter
+    UINT16_TO_BE_STREAM(p_length, param_length);
+    p_pkt->len  = p_data - p_start;
+    return AVRC_STS_NO_ERROR;
+}
+
+/**************************************************************************************
+**
+** Function                  avrc_bld_change_path_rsp
+**
+** Description
+**
+** Returns
+**
+************************************************************************************/
+static tAVRC_STS avrc_bld_change_path_rsp (tAVRC_CHG_PATH_RSP *p_rsp, BT_HDR *p_pkt )
+{
+    UINT8 *p_data, *p_start;
+    UINT16 param_len; /* parameter length feild of Rsp */
+
+    AVRC_TRACE_DEBUG("avrc_bld_change_path_rsp offset :x%x", p_pkt->offset);
+
+    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+    p_data = p_start;
+    UINT8_TO_BE_STREAM(p_data, p_rsp->pdu);
+    param_len = 5; /* refer spec */
+    UINT16_TO_BE_STREAM(p_data, param_len);
+    UINT8_TO_BE_STREAM(p_data, p_rsp->status);
+    UINT32_TO_BE_STREAM(p_data, p_rsp->num_items);
+    p_pkt->len  = p_data - p_start;
+    AVRC_TRACE_DEBUG("length = %d",p_pkt->len);
+    return AVRC_STS_NO_ERROR ;
+}
+
+/**************************************************************************************
+**
+** Function                  avrc_bld_set_browse_player_rsp
+**
+** Description
+**
+** Returns
+**
+************************************************************************************/
+static tAVRC_STS avrc_bld_set_browse_player_rsp (tAVRC_SET_BR_PLAYER_RSP *p_rsp, BT_HDR *p_pkt )
+{
+    UINT8 *p_data, *p_start;
+    UINT16 param_len_folder_name = 0;
+    UINT16 param_len; /* parameter length feild of Rsp */
+    UINT8 folder_index = 0;
+
+    AVRC_TRACE_DEBUG("avrc_bld_set_browse_player_rsp offset :x%x", p_pkt->offset);
+
+    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+    p_data = p_start;
+    UINT8_TO_BE_STREAM(p_data, p_rsp->pdu);
+
+    for(folder_index = 0; folder_index < p_rsp->folder_depth; folder_index++)
+    {
+        param_len_folder_name += p_rsp->p_folders[folder_index].str_len;
+    }
+    param_len = 10 + (p_rsp->folder_depth * 2) + param_len_folder_name; /* refer spec */
+
+    UINT16_TO_BE_STREAM(p_data, param_len);
+    UINT8_TO_BE_STREAM(p_data, p_rsp->status);
+    UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter);
+    UINT32_TO_BE_STREAM(p_data, p_rsp->num_items);
+    UINT16_TO_BE_STREAM(p_data, p_rsp->charset_id);
+    UINT8_TO_BE_STREAM(p_data, p_rsp->folder_depth);
+
+    for(folder_index = 0; folder_index < p_rsp->folder_depth; folder_index++)
+    {
+        UINT16_TO_BE_STREAM(p_data, p_rsp->p_folders[folder_index].str_len);
+        ARRAY_TO_BE_STREAM(p_data,p_rsp->p_folders[folder_index].p_str, \
+                                    p_rsp->p_folders[folder_index].str_len);
+    }
+    p_pkt->len  = p_data - p_start;
+    AVRC_TRACE_DEBUG("length = %d",p_pkt->len);
+    return AVRC_STS_NO_ERROR ;
+}
+
+/*******************************************************************************
+**
+** Function         avrc_bld_get_item_attrs_rsp
+**
+** Description      This function builds the Get Item Attributes
+**                  response.
+**
+** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
+**                  Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_get_item_attrs_rsp (tAVRC_GET_ATTRS_RSP *p_rsp, BT_HDR *p_pkt)
+{
+    UINT8   *p_data, *p_start;
+    UINT16  param_len;
+    UINT8   xx;
+
+    AVRC_TRACE_API("avrc_bld_get_item_attrs_rsp");
+    if (!p_rsp->p_attr_list)
+    {
+        AVRC_TRACE_ERROR("avrc_bld_get_item_attrs_rsp NULL parameter");
+        return AVRC_STS_BAD_PARAM;
+    }
+
+    /* get the existing length, if any, and also the num attributes */
+    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+    p_data = p_start;
+    UINT8_TO_BE_STREAM(p_data, p_rsp->pdu);
+
+    param_len = 2; /* for status and num_attr*/
+    for(xx = 0; xx < p_rsp->attr_count; xx++)
+    {
+        /* 8 for attr_id, char_set_id, attr_value_len */
+        param_len = param_len + 8 + p_rsp->p_attr_list[xx].name.str_len;
+    }
+    AVRC_TRACE_API(" param_len = %d ", param_len);
+    UINT16_TO_BE_STREAM(p_data, param_len);
+    UINT8_TO_BE_STREAM(p_data, p_rsp->status);
+    UINT8_TO_BE_STREAM(p_data, p_rsp->attr_count);
+
+    for (xx=0; xx < p_rsp->attr_count; xx++)
+    {
+        if ( !p_rsp->p_attr_list[xx].name.p_str )
+        {
+            p_rsp->p_attr_list[xx].name.str_len = 0;
+        }
+        UINT32_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].attr_id);
+        UINT16_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].name.charset_id);
+        UINT16_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].name.str_len);
+        ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].name.p_str, \
+                                    p_rsp->p_attr_list[xx].name.str_len);
+    }
+    p_pkt->len = (p_data - p_start);
+    return AVRC_STS_NO_ERROR;
+}
+
+/**************************************************************************************
+**
+** Function                  avrc_bld_change_path_rsp
+**
+** Description
+**
+** Returns
+**
+************************************************************************************/
+static tAVRC_STS avrc_bld_tot_num_items_rsp (tAVRC_GET_TOT_ITEMS_RSP *p_rsp, BT_HDR *p_pkt )
+{
+    UINT8 *p_data, *p_start;
+    UINT16 param_len; /* parameter length field of Rsp */
+
+    AVRC_TRACE_DEBUG("avrc_bld_tot_num_items_rsp offset :x%x", p_pkt->offset);
+
+    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+    p_data = p_start;
+    UINT8_TO_BE_STREAM(p_data, p_rsp->pdu);
+    param_len = 7; /* refer spec */
+    UINT16_TO_BE_STREAM(p_data, param_len);
+    UINT8_TO_BE_STREAM(p_data, p_rsp->status);
+    UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter);
+    UINT32_TO_BE_STREAM(p_data, p_rsp->num_items);
+    p_pkt->len  = p_data - p_start;
+    AVRC_TRACE_DEBUG("length = %d", p_pkt->len);
+    return AVRC_STS_NO_ERROR;
+}
+
+
 /*******************************************************************************
 **
 ** Function         avrc_bld_rejected_rsp
@@ -799,6 +1092,34 @@
 
 /*******************************************************************************
 **
+** Function         avrc_bld_browse_rejected_rsp
+**
+** Description      This function builds the Browse Reject response.
+**
+** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
+**                  Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_browse_rejected_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
+{
+    UINT8 *p_data, *p_start;
+
+    AVRC_TRACE_API("avrc_bld_browse_rejected_rsp: status=%d, pdu:x%x, offset=%d", p_rsp->status,
+                      p_rsp->pdu, p_pkt->offset);
+
+    p_start   = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+    p_data    = p_start;
+    *p_data++ = p_rsp->pdu;
+
+    UINT16_TO_BE_STREAM(p_data, 1); //Parameter length
+    UINT8_TO_BE_STREAM(p_data, p_rsp->status);
+    p_pkt->len = p_data - p_start;
+    AVRC_TRACE_DEBUG("Browse rejected rsp length=%d", p_pkt->len);
+    return AVRC_STS_NO_ERROR;
+}
+
+/*******************************************************************************
+**
 ** Function         avrc_bld_init_rsp_buffer
 **
 ** Description      This function initializes the response buffer based on PDU
@@ -990,5 +1311,115 @@
     return status;
 }
 
+/*******************************************************************************
+**
+** Function         avrc_bld_init_browse_rsp_buffer
+**
+** Description      This function initializes the response buffer based on PDU
+**
+** Returns          NULL, if no GKI buffer or failure to build the message.
+**                  Otherwise, the GKI buffer that contains the initialized message.
+**
+*******************************************************************************/
+static BT_HDR *avrc_bld_init_browse_rsp_buffer(tAVRC_RESPONSE *p_rsp)
+{
+    UINT16 offset = AVCT_BROWSE_OFFSET;
+    UINT16 chnl = AVCT_DATA_BROWSE;
+    UINT16 len  = BT_DEFAULT_BUFFER_SIZE;
+    BT_HDR *p_pkt = NULL;
+
+    AVRC_TRACE_API("avrc_bld_init_browse_rsp_buffer ");
+    /* allocate and initialize the buffer */
+    p_pkt = (BT_HDR *)osi_malloc(len);
+
+    if (p_pkt != NULL)
+    {
+        p_pkt->layer_specific = chnl;
+        p_pkt->event    = AVRC_OP_BROWSE; /* Browsing Opcode */
+        p_pkt->offset   = offset;
+    }
+    else
+    {
+        AVRC_TRACE_ERROR("### browse_rsp_buffer BUFF not allocated");
+    }
+    return p_pkt;
+}
+
+/*******************************************************************************
+**
+** Function         AVRC_BldBrowseResponse
+**
+** Description      This function builds the given AVRCP response to the given
+**                  GKI buffer
+**
+** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
+**                  Otherwise, the error code.
+**
+*******************************************************************************/
+tAVRC_STS AVRC_BldBrowseResponse( UINT8 handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_pkt)
+{
+    tAVRC_STS status = AVRC_STS_BAD_PARAM;
+    BT_HDR *p_pkt;
+    BOOLEAN alloc = FALSE;
+
+    if (!p_rsp || !pp_pkt)
+    {
+        AVRC_TRACE_ERROR("### BldResponse error p_rsp=%p, pp_pkt=%p",
+                           p_rsp, pp_pkt);
+        return AVRC_STS_BAD_PARAM;
+    }
+
+    if (*pp_pkt == NULL)
+    {
+        if ((*pp_pkt = avrc_bld_init_browse_rsp_buffer(p_rsp)) == NULL)
+        {
+            AVRC_TRACE_ERROR("### BldResponse: Failed to initialize response buffer");
+            return AVRC_STS_INTERNAL_ERR;
+        }
+        alloc = TRUE;
+    }
+    status = AVRC_STS_NO_ERROR;
+    p_pkt = *pp_pkt;
+
+    AVRC_TRACE_API("BldResponse: pdu=%x status=%x", p_rsp->rsp.pdu, p_rsp->rsp.status);
+    if (p_rsp->rsp.status != AVRC_STS_NO_ERROR)
+    {
+        AVRC_TRACE_ERROR("###ERROR AVRC_BldBrowseResponse");
+        return (avrc_bld_browse_rejected_rsp(&p_rsp->rsp, p_pkt));
+    }
+
+    switch (p_rsp->pdu)
+    {
+        case AVRC_PDU_GET_FOLDER_ITEMS:
+            status = avrc_bld_folder_item_values_rsp(&p_rsp->get_items, p_pkt);
+            break;
+
+        case AVRC_PDU_SET_BROWSED_PLAYER:
+            status = avrc_bld_set_browse_player_rsp(&p_rsp->br_player, p_pkt);
+            break;
+
+        case AVRC_PDU_CHANGE_PATH:
+            status = avrc_bld_change_path_rsp(&p_rsp->chg_path, p_pkt);
+            break;
+
+        case AVRC_PDU_GET_ITEM_ATTRIBUTES:
+            status = avrc_bld_get_item_attrs_rsp(&p_rsp->get_attrs, p_pkt);
+            break;
+
+        case AVRC_PDU_GET_TOTAL_NUMBER_OF_ITEMS:
+            status = avrc_bld_tot_num_items_rsp(&p_rsp->get_tot_items, p_pkt);
+            break;
+
+        default :
+            break;
+    }
+    if (alloc && (status != AVRC_STS_NO_ERROR) )
+    {
+        osi_free_and_reset((void **)&p_pkt);
+        *pp_pkt = NULL;
+        AVRC_TRACE_ERROR("### error status:%d",status);
+    }
+    return status;
+}
 #endif /* (AVRC_METADATA_INCLUDED == TRUE)*/
 
diff --git a/stack/avrc/avrc_int.h b/stack/avrc/avrc_int.h
index 36bb0c5..7c37300 100644
--- a/stack/avrc/avrc_int.h
+++ b/stack/avrc/avrc_int.h
@@ -42,6 +42,11 @@
 
 /* Number of protocol elements in protocol element list. */
 #define AVRC_NUM_PROTO_ELEMS     2
+#if (defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE))
+#define AVRC_NUM_ADDL_PROTO_ELEMS     2
+#else
+#define AVRC_NUM_ADDL_PROTO_ELEMS     1
+#endif
 
 #ifndef AVRC_MIN_CMD_LEN
 #define AVRC_MIN_CMD_LEN    20
diff --git a/stack/avrc/avrc_pars_ct.c b/stack/avrc/avrc_pars_ct.c
index 71e0e34..b5786ba 100644
--- a/stack/avrc/avrc_pars_ct.c
+++ b/stack/avrc/avrc_pars_ct.c
@@ -547,7 +547,7 @@
         if (len < min_len) goto length_error;
         BE_STREAM_TO_UINT32(p_result->get_play_status.song_len, p);
         BE_STREAM_TO_UINT32(p_result->get_play_status.song_pos, p);
-        BE_STREAM_TO_UINT8(p_result->get_play_status.status, p);
+        BE_STREAM_TO_UINT8(p_result->get_play_status.play_status, p);
         break;
 
     default:
diff --git a/stack/avrc/avrc_pars_tg.c b/stack/avrc/avrc_pars_tg.c
index 820e99f..81eb9db 100644
--- a/stack/avrc/avrc_pars_tg.c
+++ b/stack/avrc/avrc_pars_tg.c
@@ -342,7 +342,31 @@
 
     /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
     /* case AVRC_PDU_ABORT_CONTINUATION_RSP:   0x41 */
+    case AVRC_PDU_SET_ADDRESSED_PLAYER:
+        if (len != 2)
+        {
+           status = AVRC_STS_NOT_FOUND;
+           AVRC_TRACE_ERROR("AVRC_PDU_SET_ADDRESSED_PLAYER: bad len");
+        }
+        else
+        {
+            BE_STREAM_TO_UINT16 (p_result->addr_player.player_id, p);
+        }
+        break;
 
+    case AVRC_PDU_PLAY_ITEM:
+        if (len != 11)
+        {
+            status = AVRC_STS_NOT_FOUND;
+            AVRC_TRACE_ERROR("AVRC_PDU_PLAY_ITEM: bad len");
+        }
+        else
+        {
+            BE_STREAM_TO_UINT8 (p_result->play_item.scope, p);
+            BE_STREAM_TO_UINT64(p_result->play_item.uid, p);
+            BE_STREAM_TO_UINT16 (p_result->play_item.uid_counter, p);
+        }
+        break;
     default:
         status = AVRC_STS_BAD_CMD;
         break;
@@ -425,7 +449,7 @@
         p_result->cmd.opcode = p_msg->hdr.opcode;
         p_result->cmd.status = status;
     }
-    AVRC_TRACE_DEBUG("%s return status:0x%x", __func__, status);
+    BTIF_TRACE_IMP("AVRC_ParsCommand() return status:0x%x", status);
     return status;
 }
 
diff --git a/stack/avrc/avrc_sdp.c b/stack/avrc/avrc_sdp.c
index da26523..0a71f21 100644
--- a/stack/avrc/avrc_sdp.c
+++ b/stack/avrc/avrc_sdp.c
@@ -42,6 +42,21 @@
 tAVRC_CB avrc_cb;
 #endif
 
+#if (defined(AVCT_COVER_ART_INCLUDED) && (AVCT_COVER_ART_INCLUDED == TRUE))
+#define AVCT_CA_PSM     0X1021
+#endif
+
+/* Fix for below klockwork issue.
+ * Address of a local variable is returned through formal argument 'p_db->p_attrs' in
+ * API AVRC_FindService, removed local declaration and defined globally */
+UINT16 a2d_attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST, /* update AVRC_NUM_ATTR, if changed */
+                          ATTR_ID_PROTOCOL_DESC_LIST,
+                          ATTR_ID_BT_PROFILE_DESC_LIST,
+                          ATTR_ID_SERVICE_NAME,
+                          ATTR_ID_SUPPORTED_FEATURES,
+                          ATTR_ID_PROVIDER_NAME};
+/* update AVRC_NUM_PROTO_ELEMS if this constant is changed */
+
 /******************************************************************************
 **
 ** Function         avrc_sdp_cback
@@ -112,13 +127,6 @@
 {
     tSDP_UUID   uuid_list;
     BOOLEAN     result = TRUE;
-    UINT16      a2d_attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST, /* update AVRC_NUM_ATTR, if changed */
-                                   ATTR_ID_PROTOCOL_DESC_LIST,
-                                   ATTR_ID_BT_PROFILE_DESC_LIST,
-                                   ATTR_ID_SERVICE_NAME,
-                                   ATTR_ID_SUPPORTED_FEATURES,
-                                   ATTR_ID_PROVIDER_NAME};
-
     AVRC_TRACE_API("AVRC_FindService uuid: %x", service_uuid);
     if( (service_uuid != UUID_SERVCLASS_AV_REM_CTRL_TARGET && service_uuid != UUID_SERVCLASS_AV_REMOTE_CONTROL) ||
         p_db == NULL || p_db->p_db == NULL || p_cback == NULL)
@@ -235,20 +243,32 @@
                                                   (tSDP_PROTOCOL_ELEM *)avrc_proto_desc_list);
 
     /* additional protocal descriptor, required only for version > 1.3    */
-    if ((profile_version > AVRC_REV_1_3) && (browse_supported))
+    if ((profile_version > AVRC_REV_1_3 ) && (browse_supported))
     {
-        tSDP_PROTO_LIST_ELEM  avrc_add_proto_desc_list;
-        avrc_add_proto_desc_list.num_elems = 2;
-        avrc_add_proto_desc_list.list_elem[0].num_params = 1;
-        avrc_add_proto_desc_list.list_elem[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
-        avrc_add_proto_desc_list.list_elem[0].params[0] = AVCT_BR_PSM;
-        avrc_add_proto_desc_list.list_elem[0].params[1] = 0;
-        avrc_add_proto_desc_list.list_elem[1].num_params = 1;
-        avrc_add_proto_desc_list.list_elem[1].protocol_uuid = UUID_PROTOCOL_AVCTP;
-        avrc_add_proto_desc_list.list_elem[1].params[0] = AVCT_REV_1_4;
-        avrc_add_proto_desc_list.list_elem[1].params[1] = 0;
+        tSDP_PROTO_LIST_ELEM  avrc_add_proto_desc_list[AVRC_NUM_ADDL_PROTO_ELEMS];
+        avrc_add_proto_desc_list[0].num_elems = 2;
+        avrc_add_proto_desc_list[0].list_elem[0].num_params = 1;
+        avrc_add_proto_desc_list[0].list_elem[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
+        avrc_add_proto_desc_list[0].list_elem[0].params[0] = AVCT_BR_PSM;
+        avrc_add_proto_desc_list[0].list_elem[0].params[1] = 0;
+        avrc_add_proto_desc_list[0].list_elem[1].num_params = 1;
+        avrc_add_proto_desc_list[0].list_elem[1].protocol_uuid = UUID_PROTOCOL_AVCTP;
+        avrc_add_proto_desc_list[0].list_elem[1].params[0] = AVCT_REV_1_4;
+        avrc_add_proto_desc_list[0].list_elem[1].params[1] = 0;
+        for (index = 1; index < AVRC_NUM_ADDL_PROTO_ELEMS; index++)
+        {
+            avrc_add_proto_desc_list[index].num_elems = 2;
+            avrc_add_proto_desc_list[index].list_elem[0].num_params = 1;
+            avrc_add_proto_desc_list[index].list_elem[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
+            avrc_add_proto_desc_list[index].list_elem[0].params[0] = AVCT_CA_PSM;
+            avrc_add_proto_desc_list[index].list_elem[0].params[1] = 0;
+            avrc_add_proto_desc_list[index].list_elem[1].num_params = 0;
+            avrc_add_proto_desc_list[index].list_elem[1].protocol_uuid = UUID_PROTOCOL_OBEX;
+            avrc_add_proto_desc_list[index].list_elem[1].params[0] = 0;
+            avrc_add_proto_desc_list[index].list_elem[1].params[1] = 0;
 
-        result &= SDP_AddAdditionProtoLists( sdp_handle, 1, (tSDP_PROTO_LIST_ELEM *)&avrc_add_proto_desc_list);
+        }
+        result &= SDP_AddAdditionProtoLists( sdp_handle, AVRC_NUM_ADDL_PROTO_ELEMS, (tSDP_PROTO_LIST_ELEM *)avrc_add_proto_desc_list);
     }
     /* add profile descriptor list   */
     result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, profile_version);
diff --git a/stack/btm/btm_acl.c b/stack/btm/btm_acl.c
index 4819012..481a6ce 100644
--- a/stack/btm/btm_acl.c
+++ b/stack/btm/btm_acl.c
@@ -47,7 +47,7 @@
 #include "l2c_int.h"
 #include "hcidefs.h"
 #include "bt_utils.h"
-
+#include "device/include/interop_config.h"
 
 extern fixed_queue_t *btu_general_alarm_queue;
 
@@ -217,7 +217,7 @@
     tACL_CONN        *p;
     UINT8             xx;
 
-    BTM_TRACE_DEBUG ("btm_acl_created hci_handle=%d link_role=%d  transport=%d",
+    BTM_TRACE_WARNING ("btm_acl_created hci_handle=%d link_role=%d  transport=%d",
                       hci_handle,link_role, transport);
     /* Ensure we don't have duplicates */
     p = btm_bda_to_acl(bda, transport);
@@ -257,6 +257,7 @@
 
 #endif
 #endif
+            p->switch_role_failed_attempts = 0;
             p->switch_role_state = BTM_ACL_SWKEY_STATE_IDLE;
 
             btm_pm_sm_alloc(xx);
@@ -271,7 +272,6 @@
             /* if BR/EDR do something more */
             if (transport == BT_TRANSPORT_BR_EDR)
             {
-                btsnd_hcic_read_rmt_clk_offset (p->hci_handle);
                 btsnd_hcic_rmt_ver_req (p->hci_handle);
             }
             p_dev_rec = btm_find_dev_by_handle (hci_handle);
@@ -328,11 +328,7 @@
                     btm_establish_continue(p);
                 }
             }
-            else
 #endif
-            {
-                btm_read_remote_features (p->hci_handle);
-            }
 
             /* read page 1 - on rmt feature event for buffer reasons */
             return;
@@ -498,48 +494,53 @@
 void btm_acl_update_busy_level (tBTM_BLI_EVENT event)
 {
     tBTM_BL_UPDATE_DATA  evt;
-    UINT8 busy_level;
+    UINT8 busy_level = btm_cb.busy_level;
     BTM_TRACE_DEBUG ("btm_acl_update_busy_level");
     BOOLEAN old_inquiry_state = btm_cb.is_inquiry;
+    /*Initialize busy_level_flags to 0*/
+    evt.busy_level_flags = 0;
     switch (event)
     {
         case BTM_BLI_ACL_UP_EVT:
             BTM_TRACE_DEBUG ("BTM_BLI_ACL_UP_EVT");
+            busy_level = BTM_GetNumAclLinks();
             break;
         case BTM_BLI_ACL_DOWN_EVT:
             BTM_TRACE_DEBUG ("BTM_BLI_ACL_DOWN_EVT");
+            busy_level = BTM_GetNumAclLinks();
             break;
         case BTM_BLI_PAGE_EVT:
             BTM_TRACE_DEBUG ("BTM_BLI_PAGE_EVT");
             btm_cb.is_paging = TRUE;
             evt.busy_level_flags= BTM_BL_PAGING_STARTED;
+            busy_level = BTM_BL_PAGING_STARTED;
             break;
         case BTM_BLI_PAGE_DONE_EVT:
             BTM_TRACE_DEBUG ("BTM_BLI_PAGE_DONE_EVT");
             btm_cb.is_paging = FALSE;
             evt.busy_level_flags = BTM_BL_PAGING_COMPLETE;
+            busy_level = BTM_BL_PAGING_COMPLETE;
             break;
         case BTM_BLI_INQ_EVT:
             BTM_TRACE_DEBUG ("BTM_BLI_INQ_EVT");
             btm_cb.is_inquiry = TRUE;
             evt.busy_level_flags = BTM_BL_INQUIRY_STARTED;
+            busy_level = BTM_BL_INQUIRY_STARTED;
             break;
         case BTM_BLI_INQ_CANCEL_EVT:
             BTM_TRACE_DEBUG ("BTM_BLI_INQ_CANCEL_EVT");
             btm_cb.is_inquiry = FALSE;
             evt.busy_level_flags = BTM_BL_INQUIRY_CANCELLED;
+            busy_level = BTM_BL_INQUIRY_COMPLETE;
             break;
         case BTM_BLI_INQ_DONE_EVT:
             BTM_TRACE_DEBUG ("BTM_BLI_INQ_DONE_EVT");
             btm_cb.is_inquiry = FALSE;
             evt.busy_level_flags = BTM_BL_INQUIRY_COMPLETE;
+            busy_level = BTM_BL_INQUIRY_COMPLETE;
             break;
     }
 
-    if (btm_cb.is_paging || btm_cb.is_inquiry)
-        busy_level = 10;
-    else
-        busy_level = BTM_GetNumAclLinks();
 
     if ((busy_level != btm_cb.busy_level) ||(old_inquiry_state != btm_cb.is_inquiry))
     {
@@ -576,6 +577,10 @@
 
     /* Get the current role */
     *p_role = p->link_role;
+    BTM_TRACE_WARNING ("BTM: Local device role : 0x%02x", *p_role );
+    BTM_TRACE_WARNING ("BTM: RemBdAddr: %02x%02x%02x%02x%02x%02x",
+                        remote_bd_addr[0], remote_bd_addr[1], remote_bd_addr[2], remote_bd_addr[3],
+                        remote_bd_addr[4], remote_bd_addr[5]);
     return(BTM_SUCCESS);
 }
 
@@ -610,12 +615,9 @@
 #if (BT_USE_TRACES == TRUE)
     BD_ADDR_PTR  p_bda;
 #endif
-    BTM_TRACE_API ("BTM_SwitchRole BDA: %02x-%02x-%02x-%02x-%02x-%02x",
-                    remote_bd_addr[0], remote_bd_addr[1], remote_bd_addr[2],
-                    remote_bd_addr[3], remote_bd_addr[4], remote_bd_addr[5]);
 
-    /* Make sure the local device supports switching */
-    if (!controller_get_interface()->supports_master_slave_role_switch())
+    /* Make sure the local/remote devices supports switching */
+    if (!btm_dev_support_switch(remote_bd_addr))
         return(BTM_MODE_UNSUPPORTED);
 
     if (btm_cb.devcb.p_switch_role_cb && p_cb)
@@ -632,8 +634,10 @@
     if ((p = btm_bda_to_acl(remote_bd_addr, BT_TRANSPORT_BR_EDR)) == NULL)
         return(BTM_UNKNOWN_ADDR);
 
+    bt_bdaddr_t remote_address;
+    bdcpy(remote_address.address, remote_bd_addr);
     /* Finished if already in desired role */
-    if (p->link_role == new_role)
+    if ((p->link_role == new_role) || (interop_database_match_addr(INTEROP_DISABLE_ROLE_SWITCH, (bt_bdaddr_t *)&remote_address)))
         return(BTM_SUCCESS);
 
 #if BTM_SCO_INCLUDED == TRUE
@@ -652,6 +656,32 @@
         return(BTM_BUSY);
     }
 
+    if (interop_database_match_addr(INTEROP_DYNAMIC_ROLE_SWITCH, (bt_bdaddr_t *)&remote_address))
+    {
+#if (defined(BTM_SAFE_REATTEMPT_ROLE_SWITCH) && BTM_SAFE_REATTEMPT_ROLE_SWITCH == TRUE)
+        p_dev_rec = btm_find_dev (remote_bd_addr);
+        if(!p_dev_rec || (p_dev_rec->switch_role_attempts >= BTM_MAX_BL_SW_ROLE_ATTEMPTS))
+        {
+            BTM_TRACE_DEBUG (" Below device is Blacklisted ....");
+            BTM_TRACE_DEBUG (" SwitchRole can't be initiated for 0x%02x%02x%02x%02x%02x%02x",
+                          remote_bd_addr[0], remote_bd_addr[1], remote_bd_addr[2],
+                          remote_bd_addr[3], remote_bd_addr[4], remote_bd_addr[5]);
+            return BTM_REPEATED_ATTEMPTS;
+        }
+        else
+        {
+            BTM_TRACE_DEBUG (" Device blacklisted, trying for role change again");
+            p_dev_rec->switch_role_attempts++;
+        }
+#else
+        BTM_TRACE_DEBUG (" Below device is Blacklisted ....");
+        BTM_TRACE_DEBUG (" SwitchRole can't be initiated for 0x%02x%02x%02x%02x%02x%02x",
+                remote_bd_addr[0], remote_bd_addr[1], remote_bd_addr[2],
+                remote_bd_addr[3], remote_bd_addr[4], remote_bd_addr[5]);
+        return BTM_REPEATED_ATTEMPTS;
+#endif
+    }
+
     if ((status = BTM_ReadPowerMode(p->remote_addr, &pwr_mode)) != BTM_SUCCESS)
         return(status);
 
@@ -709,6 +739,10 @@
         btm_cb.devcb.switch_role_ref_data.hci_status = HCI_ERR_UNSUPPORTED_VALUE;
         btm_cb.devcb.p_switch_role_cb = p_cb;
     }
+    BTM_TRACE_WARNING ("BTM_SwitchRole BDA: %02x-%02x-%02x-%02x-%02x-%02x",
+    remote_bd_addr[0], remote_bd_addr[1], remote_bd_addr[2],
+    remote_bd_addr[3], remote_bd_addr[4], remote_bd_addr[5]);
+    BTM_TRACE_WARNING ("Requested New Role: %d", new_role)
     return(BTM_CMD_STARTED);
 }
 
@@ -735,10 +769,15 @@
                       handle, status, encr_enable);
     xx = btm_handle_to_acl_index(handle);
     /* don't assume that we can never get a bad hci_handle */
-    if (xx < MAX_L2CAP_LINKS)
+    if (xx < MAX_L2CAP_LINKS) {
         p = &btm_cb.acl_db[xx];
-    else
+    } else {
+        GENERATE_VENDOR_LOGS();
         return;
+    }
+
+    if (status != HCI_SUCCESS)
+        GENERATE_VENDOR_LOGS();
 
     /* Process Role Switch if active */
     if (p->switch_role_state == BTM_ACL_SWKEY_STATE_ENCRYPTION_OFF)
@@ -825,11 +864,19 @@
     /* First, check if hold mode is supported */
     if (*settings != HCI_DISABLE_ALL_LM_MODES)
     {
+        bt_bdaddr_t remote_address;
+        bdcpy(remote_address.address, remote_bda);
         if ( (*settings & HCI_ENABLE_MASTER_SLAVE_SWITCH) && (!HCI_SWITCH_SUPPORTED(localFeatures)) )
         {
             *settings &= (~HCI_ENABLE_MASTER_SLAVE_SWITCH);
             BTM_TRACE_API ("BTM_SetLinkPolicy switch not supported (settings: 0x%04x)", *settings );
         }
+        if ( (*settings & HCI_ENABLE_MASTER_SLAVE_SWITCH) &&
+            (interop_database_match_addr(INTEROP_DISABLE_ROLE_SWITCH_POLICY, (bt_bdaddr_t *)&remote_address)) )
+        {
+            *settings &= (~HCI_ENABLE_MASTER_SLAVE_SWITCH);
+            BTM_TRACE_API ("BTM_SetLinkPolicy switch not supported (settings: 0x%04x)", *settings );
+        }
         if ( (*settings & HCI_ENABLE_HOLD_MODE) && (!HCI_HOLD_MODE_SUPPORTED(localFeatures)) )
         {
             *settings &= (~HCI_ENABLE_HOLD_MODE);
@@ -966,6 +1013,11 @@
                 STREAM_TO_UINT8  (p_acl_cb->lmp_version, p);
                 STREAM_TO_UINT16 (p_acl_cb->manufacturer, p);
                 STREAM_TO_UINT16 (p_acl_cb->lmp_subversion, p);
+                if (p_acl_cb->transport == BT_TRANSPORT_BR_EDR)
+                {
+                    BTM_TRACE_DEBUG("Calling btm_read_remote_features");
+                    btm_read_remote_features (p_acl_cb->hci_handle);
+                }
             }
 
 #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
@@ -974,12 +1026,16 @@
                 btm_use_preferred_conn_params(p_acl_cb->remote_addr);
             }
 #endif  // (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+                BTM_TRACE_WARNING ("btm_read_remote_version_complete: BDA: %02x-%02x-%02x-%02x-%02x-%02x",
+                                     p_acl_cb->remote_addr[0], p_acl_cb->remote_addr[1], p_acl_cb->remote_addr[2],
+                                     p_acl_cb->remote_addr[3], p_acl_cb->remote_addr[4], p_acl_cb->remote_addr[5]);
+                BTM_TRACE_WARNING ("btm_read_remote_version_complete lmp_version %d manufacturer %d lmp_subversion %d",
+                                       p_acl_cb->lmp_version,p_acl_cb->manufacturer, p_acl_cb->lmp_subversion);
             break;
         }
     }
 }
 
-
 /*******************************************************************************
 **
 ** Function         btm_process_remote_ext_features
@@ -995,6 +1051,7 @@
     UINT16              handle = p_acl_cb->hci_handle;
     tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_dev_by_handle (handle);
     UINT8               page_idx;
+    UINT8             status;
 
     BTM_TRACE_DEBUG ("btm_process_remote_ext_features");
 
@@ -1020,6 +1077,12 @@
                 HCI_FEATURE_BYTES_PER_PAGE);
     }
 
+    if (!(p_dev_rec->sec_flags & BTM_SEC_NAME_KNOWN) || p_dev_rec->is_originator)
+    {
+        BTM_TRACE_DEBUG ("Calling Next Security Procedure");
+        if ((status = btm_sec_execute_procedure (p_dev_rec)) != BTM_CMD_STARTED)
+            btm_sec_dev_rec_cback_event (p_dev_rec, status , FALSE);
+    }
     const UINT8 req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND);
 
     /* Store the Peer Security Capabilites (in SM4 and rmt_sec_caps) */
@@ -1266,24 +1329,28 @@
                 BTM_SetLinkPolicy (p_acl_cb->remote_addr, &btm_cb.btm_def_link_policy);
         }
 #endif
-        p_acl_cb->link_up_issued = TRUE;
-
-        /* If anyone cares, tell him database changed */
-        if (btm_cb.p_bl_changed_cb)
+        if(p_acl_cb->link_up_issued == FALSE)
         {
-            evt_data.event = BTM_BL_CONN_EVT;
-            evt_data.conn.p_bda = p_acl_cb->remote_addr;
-            evt_data.conn.p_bdn = p_acl_cb->remote_name;
-            evt_data.conn.p_dc  = p_acl_cb->remote_dc;
-            evt_data.conn.p_features = p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0];
+
+            p_acl_cb->link_up_issued = TRUE;
+
+            /* If anyone cares, tell him database changed */
+            if (btm_cb.p_bl_changed_cb)
+            {
+                evt_data.event = BTM_BL_CONN_EVT;
+                evt_data.conn.p_bda = p_acl_cb->remote_addr;
+                evt_data.conn.p_bdn = p_acl_cb->remote_name;
+                evt_data.conn.p_dc  = p_acl_cb->remote_dc;
+                evt_data.conn.p_features = p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0];
 #if BLE_INCLUDED == TRUE
-            evt_data.conn.handle = p_acl_cb->hci_handle;
-            evt_data.conn.transport = p_acl_cb->transport;
+                evt_data.conn.handle = p_acl_cb->hci_handle;
+                evt_data.conn.transport = p_acl_cb->transport;
 #endif
 
-            (*btm_cb.p_bl_changed_cb)(&evt_data);
-        }
-        btm_acl_update_busy_level (BTM_BLI_ACL_UP_EVT);
+                (*btm_cb.p_bl_changed_cb)(&evt_data);
+            }
+            btm_acl_update_busy_level (BTM_BLI_ACL_UP_EVT);
+       }
 }
 
 
@@ -1478,6 +1545,59 @@
 
 /*******************************************************************************
 **
+** Function         btm_blacklist_role_change_device
+**
+** Description      This function is used to blacklist the device if the role
+**                  switch fails for maximum number of times. It also removes
+**                  the device from black list if the role switch succedes.
+
+** Input Parms      bd_addr - remote BD addr
+**                  hci_status - role switch status
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_blacklist_role_change_device (BD_ADDR bd_addr, UINT8 hci_status)
+{
+    tACL_CONN  *p = btm_bda_to_acl(bd_addr, BT_TRANSPORT_BR_EDR);
+    tBTM_SEC_DEV_REC  *p_dev_rec = btm_find_dev (bd_addr);
+    UINT32 cod = 0;
+    bt_bdaddr_t remote_bdaddr;
+    bdcpy(remote_bdaddr.address, bd_addr);
+
+    if(!p || !p_dev_rec)
+    {
+        return;
+    }
+    cod = (p_dev_rec->dev_class[2]) | (p_dev_rec->dev_class[1] << 8) |
+          (p_dev_rec->dev_class[0] << 16);
+
+    /* check for carkits */
+    if ((hci_status != HCI_SUCCESS) &&
+        ((p->switch_role_state == BTM_ACL_SWKEY_STATE_SWITCHING) ||
+         (p->switch_role_state == BTM_ACL_SWKEY_STATE_IN_PROGRESS)) &&
+        ((cod & COD_AUDIO_DEVICE) == COD_AUDIO_DEVICE) &&
+        (!interop_database_match_addr(INTEROP_DYNAMIC_ROLE_SWITCH, (bt_bdaddr_t *)&remote_bdaddr)))
+    {
+        p->switch_role_failed_attempts++;
+        if(p->switch_role_failed_attempts == BTM_MAX_SW_ROLE_FAILED_ATTEMPTS)
+        {
+            BTM_TRACE_WARNING ("btm_blacklist_device: BDA: %02x-%02x-%02x-%02x-%02x-%02x",
+                bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
+            interop_database_add_addr(INTEROP_DYNAMIC_ROLE_SWITCH, (bt_bdaddr_t *)&remote_bdaddr, 3);
+        }
+    }
+    else if(hci_status == HCI_SUCCESS)
+    {
+#if (defined(BTM_SAFE_REATTEMPT_ROLE_SWITCH) && BTM_SAFE_REATTEMPT_ROLE_SWITCH == TRUE)
+        interop_database_remove_addr(INTEROP_DYNAMIC_ROLE_SWITCH, (bt_bdaddr_t *)&remote_bdaddr);
+#endif
+        p->switch_role_failed_attempts = 0;
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         btm_acl_role_changed
 **
 ** Description      This function is called whan a link's master/slave role change
@@ -1498,12 +1618,17 @@
     tBTM_BL_ROLE_CHG_DATA   evt;
 
     BTM_TRACE_DEBUG ("btm_acl_role_changed");
+    BTM_TRACE_WARNING ("btm_acl_role_changed: BDA: %02x-%02x-%02x-%02x-%02x-%02x",
+                          p_bda[0], p_bda[1], p_bda[2], p_bda[3], p_bda[4], p_bda[5]);
+    BTM_TRACE_WARNING ("btm_acl_role_changed: New role: %d", new_role);
     /* Ignore any stray events */
     if (p == NULL)
     {
         /* it could be a failure */
         if (hci_status != HCI_SUCCESS)
             btm_acl_report_role_change(hci_status, bd_addr);
+
+        GENERATE_VENDOR_LOGS();
         return;
     }
 
@@ -1526,6 +1651,7 @@
     else
     {
         /* so the BTM_BL_ROLE_CHG_EVT uses the old role */
+        GENERATE_VENDOR_LOGS();
         new_role = p->link_role;
     }
 
@@ -1629,7 +1755,7 @@
     /* Make sure we don't exceed max port range.
      * Stack reserves scn 1 for HFP, HSP we still do the correct way.
      */
-    if ( (scn>=BTM_MAX_SCN) || (scn == 1) )
+    if ( (scn>=BTM_MAX_SCN) || (scn <= 1) )
         return FALSE;
 
     /* check if this port is available */
@@ -1654,7 +1780,7 @@
 BOOLEAN BTM_FreeSCN(UINT8 scn)
 {
     BTM_TRACE_DEBUG ("BTM_FreeSCN ");
-    if (scn <= BTM_MAX_SCN)
+    if (scn <= BTM_MAX_SCN && scn > 0)
     {
         btm_cb.btm_scn[scn-1] = FALSE;
         return(TRUE);
@@ -2253,10 +2379,12 @@
 *******************************************************************************/
 void btm_read_rssi_timeout(UNUSED_ATTR void *data)
 {
+    tBTM_RSSI_RESULTS  results;
     tBTM_CMPL_CB  *p_cb = btm_cb.devcb.p_rssi_cmpl_cb;
     btm_cb.devcb.p_rssi_cmpl_cb = NULL;
+    results.status = BTM_DEVICE_TIMEOUT;
     if (p_cb)
-        (*p_cb)((void *) NULL);
+        (*p_cb)(&results);
 }
 
 /*******************************************************************************
@@ -2620,6 +2748,7 @@
 {
     tBTM_BL_EVENT_DATA  evt_data;
 
+    GENERATE_VENDOR_LOGS();
     /* Report possible collision to the upper layer. */
     if (btm_cb.p_bl_changed_cb)
     {
diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c
index fe44525..04f800c 100644
--- a/stack/btm/btm_ble.c
+++ b/stack/btm/btm_ble.c
@@ -33,6 +33,7 @@
 
 #include "bt_types.h"
 #include "bt_utils.h"
+#include "btif/include/btif_storage.h"
 #include "btm_ble_api.h"
 #include "btm_int.h"
 #include "btu.h"
@@ -121,6 +122,37 @@
 
 /*******************************************************************************
 **
+** Function         BTM_GetRemoteDeviceName
+**
+** Description      This function is called to get the dev name of remote device
+**                  from NV
+**
+** Returns          TRUE if success; otherwise failed.
+**
+*******************************************************************************/
+BOOLEAN BTM_GetRemoteDeviceName(BD_ADDR bda, BD_NAME bd_name)
+{
+    BTM_TRACE_DEBUG("%s", __func__);
+    BOOLEAN ret = FALSE;
+    bt_bdname_t bdname;
+    bt_property_t prop_name;
+    bt_bdaddr_t bd_addr;
+    bdcpy(bd_addr.address, bda);
+
+    BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_BDNAME,
+                          sizeof(bt_bdname_t), &bdname);
+    if (btif_storage_get_remote_device_property(
+        &bd_addr, &prop_name) == BT_STATUS_SUCCESS)
+    {
+        APPL_TRACE_DEBUG("%s, NV name = %s", __func__, bdname.name);
+        strlcpy((char*) bd_name, (char*) bdname.name, BD_NAME_LEN);
+        ret = TRUE;
+    }
+    return ret;
+}
+
+/*******************************************************************************
+**
 ** Function         BTM_SecAddBleKey
 **
 ** Description      Add/modify LE device information.  This function will be
@@ -756,6 +788,31 @@
 
 /*******************************************************************************
 **
+** Function         BTM_BleEnhReceiverTest
+**
+** Description      This function is called to start the LE Enhanced Receiver
+**                  test
+**
+** Parameter        rx_freq - Frequency Range
+**                  phy - Phy to be used
+**                  mod_index - Modulation index
+**                  p_cmd_cmpl_cback - Command Complete callback
+**
+*******************************************************************************/
+void BTM_BleEnhReceiverTest(UINT8 rx_freq, UINT8 phy, UINT8 mod_index,
+                              tBTM_CMPL_CB *p_cmd_cmpl_cback)
+{
+     btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
+
+     if (btsnd_hcic_ble_enh_receiver_test(rx_freq, phy, mod_index) == FALSE)
+     {
+          BTM_TRACE_ERROR("%s: Unable to Trigger LE Enhanced receiver test",
+                               __FUNCTION__);
+     }
+}
+
+/*******************************************************************************
+**
 ** Function         BTM_BleTransmitterTest
 **
 ** Description      This function is called to start the LE Transmitter test
@@ -778,6 +835,32 @@
 
 /*******************************************************************************
 **
+** Function         BTM_BleEnhTransmitterTest
+**
+** Description      This function is called to start the LE Enhanced Transmitter test
+**
+** Parameter        tx_freq - Frequency Range
+**                  test_data_len - Length in bytes of payload data in each packet
+**                  packet_payload - Pattern to use in the payload
+**                  phy - Phy to be used
+**                  p_cmd_cmpl_cback - Command Complete callback
+**
+*******************************************************************************/
+void BTM_BleEnhTransmitterTest(UINT8 tx_freq, UINT8 test_data_len,
+                                 UINT8 packet_payload, UINT8 phy,
+                                 tBTM_CMPL_CB *p_cmd_cmpl_cback)
+{
+     btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
+     if (btsnd_hcic_ble_enh_transmitter_test(tx_freq, test_data_len,
+              packet_payload, phy) == FALSE)
+     {
+          BTM_TRACE_ERROR("%s: Unable to Trigger LE Enhanced transmitter test",
+                               __FUNCTION__);
+     }
+}
+
+/*******************************************************************************
+**
 ** Function         BTM_BleTestEnd
 **
 ** Description      This function is called to stop the in-progress TX or RX test
@@ -854,6 +937,8 @@
 tBTM_STATUS BTM_SetBleDataLength(BD_ADDR bd_addr, UINT16 tx_pdu_length)
 {
     tACL_CONN *p_acl = btm_bda_to_acl(bd_addr, BT_TRANSPORT_LE);
+    UINT16 tx_time = BTM_BLE_DATA_TX_TIME_MAX_LEGACY;
+
     BTM_TRACE_DEBUG("%s: tx_pdu_length =%d", __FUNCTION__, tx_pdu_length);
 
     if (!controller_get_interface()->supports_ble_packet_extension())
@@ -875,9 +960,11 @@
         else if (tx_pdu_length < BTM_BLE_DATA_SIZE_MIN)
             tx_pdu_length =  BTM_BLE_DATA_SIZE_MIN;
 
+        if (controller_get_interface()->get_bt_version()->hci_version >= HCI_PROTO_VERSION_5_0)
+            tx_time = BTM_BLE_DATA_TX_TIME_MAX;
+
         /* always set the TxTime to be max, as controller does not care for now */
-        btsnd_hcic_ble_set_data_length(p_acl->hci_handle, tx_pdu_length,
-                                            BTM_BLE_DATA_TX_TIME_MAX);
+        btsnd_hcic_ble_set_data_length(p_acl->hci_handle, tx_pdu_length, tx_time);
 
         return BTM_SUCCESS;
     }
@@ -979,6 +1066,47 @@
 
 /*******************************************************************************
 **
+** Function         BTM_SetBlePhy
+**
+** Description      This function is to set BLE tx and rx PHY
+**
+** Returns          BTM_SUCCESS if success; otherwise failed.
+**
+*******************************************************************************/
+tBTM_STATUS BTM_SetBlePhy(BD_ADDR bd_addr, UINT8 all_phy, UINT8 tx_phy,
+                          UINT8 rx_phy, UINT16 phy_options)
+{
+    tACL_CONN *p_acl = btm_bda_to_acl(bd_addr, BT_TRANSPORT_LE);
+    BTM_TRACE_DEBUG("%s: all_phy=0x%0x, tx_phy=0x%0x, rx_phy=0x%0x",
+                    __func__, all_phy, tx_phy, rx_phy);
+
+    if (!controller_get_interface()->supports_ble_two_mbps_rate())
+    {
+        BTM_TRACE_ERROR("%s failed, request not supported", __func__);
+        return BTM_ILLEGAL_VALUE;
+    }
+
+    if ((p_acl != NULL) && (!HCI_LE_TWO_MBPS_SUPPORTED(p_acl->peer_le_features)))
+    {
+        BTM_TRACE_ERROR("%s failed, peer does not support request", __func__);
+        return BTM_ILLEGAL_VALUE;
+    }
+
+    if (p_acl != NULL)
+    {
+        btsnd_hcic_ble_set_data_rate (p_acl->hci_handle, all_phy, tx_phy,
+                                      rx_phy, phy_options);
+        return BTM_SUCCESS;
+    }
+    else
+    {
+        BTM_TRACE_ERROR("%s: Wrong mode: no LE link exist or LE not supported",__func__);
+        return BTM_WRONG_MODE;
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         btm_ble_start_sec_check
 **
 ** Description      This function is to check and set the security required for
@@ -1053,6 +1181,30 @@
 
 /*******************************************************************************
 **
+** Function         BTM_SetDefaultBlePhy
+**
+** Description      This function is to set default BLE tx and rx PHY
+**
+** Returns          BTM_SUCCESS if success; otherwise failed.
+**
+*******************************************************************************/
+tBTM_STATUS BTM_SetDefaultBlePhy(UINT8 all_phy, UINT8 tx_phy, UINT8 rx_phy)
+{
+    BTM_TRACE_DEBUG("%s: all_phy=0x%0x, tx_phy=0x%0x, rx_phy=0x%0x",
+                    __func__, all_phy, tx_phy, rx_phy);
+
+    if (!controller_get_interface()->supports_ble_two_mbps_rate())
+    {
+        BTM_TRACE_ERROR("%s failed, request not supported", __func__);
+        return BTM_ILLEGAL_VALUE;
+    }
+
+    btsnd_hcic_ble_set_default_data_rate (all_phy, tx_phy, rx_phy);
+    return BTM_SUCCESS;
+}
+
+/*******************************************************************************
+**
 ** Function         btm_ble_rand_enc_complete
 **
 ** Description      This function is the callback functions for HCI_Rand command
@@ -1807,21 +1959,30 @@
 ** Returns          void
 **
 *******************************************************************************/
-static void btm_ble_resolve_random_addr_on_conn_cmpl(void * p_rec, void *p_data)
+static void btm_ble_resolve_random_addr_on_conn_cmpl(void * p_rec, void *p_data, BOOLEAN extended)
 {
     UINT8   *p = (UINT8 *)p_data;
     tBTM_SEC_DEV_REC    *match_rec = (tBTM_SEC_DEV_REC *) p_rec;
-    UINT8       role, bda_type;
+    UINT8       role, bda_type, sub_code;
     UINT16      handle;
     BD_ADDR     bda;
+    BD_ADDR     local_rpa, peer_rpa;
     UINT16      conn_interval, conn_latency, conn_timeout;
     BOOLEAN     match = FALSE;
+    UNUSED(extended);
 
+    --p;
+    STREAM_TO_UINT8(sub_code, p);
     ++p;
     STREAM_TO_UINT16   (handle, p);
     STREAM_TO_UINT8    (role, p);
     STREAM_TO_UINT8    (bda_type, p);
     STREAM_TO_BDADDR   (bda, p);
+    if (sub_code == BTM_BLE_ENHC_CONN_SUB_CODE)
+    {
+        STREAM_TO_BDADDR   (local_rpa, p);
+        STREAM_TO_BDADDR   (peer_rpa, p);
+    }
     STREAM_TO_UINT16   (conn_interval, p);
     STREAM_TO_UINT16   (conn_latency, p);
     STREAM_TO_UINT16   (conn_timeout, p);
@@ -1975,7 +2136,7 @@
            the device has been paired */
         if (!match && BTM_BLE_IS_RESOLVE_BDA(bda))
         {
-            btm_ble_resolve_random_addr(bda, btm_ble_resolve_random_addr_on_conn_cmpl, p_data);
+            btm_ble_resolve_random_addr(bda, btm_ble_resolve_random_addr_on_conn_cmpl, p_data, FALSE);
         }
         else
 #endif
@@ -1990,16 +2151,16 @@
             l2cble_conn_comp (handle, role, bda, bda_type, conn_interval,
                               conn_latency, conn_timeout);
 
-#if (BLE_PRIVACY_SPT == TRUE)
-            if (enhanced)
-            {
-                btm_ble_refresh_local_resolvable_private_addr(bda, local_rpa);
-
-                if (peer_addr_type & BLE_ADDR_TYPE_ID_BIT)
-                    btm_ble_refresh_peer_resolvable_private_addr(bda, peer_rpa, BLE_ADDR_RANDOM);
-            }
-#endif
         }
+#if (BLE_PRIVACY_SPT == TRUE)
+        if (enhanced)
+        {
+            btm_ble_refresh_local_resolvable_private_addr(bda, local_rpa);
+
+            if (peer_addr_type & BLE_ADDR_TYPE_ID_BIT)
+                btm_ble_refresh_peer_resolvable_private_addr(bda, peer_rpa, BLE_ADDR_RANDOM);
+        }
+#endif
     }
     else
     {
@@ -2089,7 +2250,7 @@
                    (*btm_cb.api.p_le_callback) (event, bd_addr, (tBTM_LE_EVT_DATA *)p_data);
                 }
 
-                if (event == SMP_COMPLT_EVT)
+                if (event == SMP_COMPLT_EVT && !p_data->cmplt.smp_over_br)
                 {
                     p_dev_rec = btm_find_dev(bd_addr);
                     if (p_dev_rec == NULL)
@@ -2129,6 +2290,7 @@
                     {
                         BTM_TRACE_DEBUG ("Pairing failed - prepare to remove ACL");
                         l2cu_start_post_bond_timer(p_dev_rec->ble_hci_handle);
+                        GENERATE_VENDOR_LOGS();
                     }
 #endif
 
@@ -2696,6 +2858,47 @@
     }
 }
 
+/*******************************************************************************
+**
+** Function         btm_ble_set_random_address
+**
+** Description      This function set a random address to local controller.
+**                  It also temporarily disable scans and adv before sending
+**                  the command to the controller
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_set_random_address(BD_ADDR random_bda)
+{
+    tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+    tBTM_BLE_CB *p_ble_cb = &btm_cb.ble_ctr_cb;
+    BOOLEAN     adv_mode = btm_cb.ble_ctr_cb.inq_var.adv_mode;
+
+    BTM_TRACE_DEBUG ("%s", __func__);
+    if (btm_ble_get_conn_st() == BLE_DIR_CONN)
+    {
+        BTM_TRACE_ERROR("%s: Cannot set random address. Direct conn ongoing", __func__);
+        return;
+    }
+
+    if (adv_mode  == BTM_BLE_ADV_ENABLE)
+        btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE);
+    if (BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity))
+        btm_ble_stop_scan();
+    btm_ble_suspend_bg_conn();
+
+    memcpy(p_cb->private_addr, random_bda, BD_ADDR_LEN);
+    btsnd_hcic_ble_set_random_addr(p_cb->private_addr);
+
+    if (adv_mode  == BTM_BLE_ADV_ENABLE)
+        btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE);
+    if (BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity))
+        btm_ble_start_scan();
+    btm_ble_resume_bg_conn();
+
+}
+
     #if BTM_BLE_CONFORMANCE_TESTING == TRUE
 /*******************************************************************************
 **
@@ -2789,6 +2992,7 @@
     btm_cb.devcb.keep_rfu_in_auth_req = keep_rfu;
 }
 
+
 #endif /* BTM_BLE_CONFORMANCE_TESTING */
 
 #endif /* BLE_INCLUDED */
diff --git a/stack/btm/btm_ble_addr.c b/stack/btm/btm_ble_addr.c
index 81fff53..b1b7167 100644
--- a/stack/btm/btm_ble_addr.c
+++ b/stack/btm/btm_ble_addr.c
@@ -60,7 +60,7 @@
         p_cb->private_addr[4] = p->param_buf[1];
         p_cb->private_addr[3] = p->param_buf[2];
         /* set it to controller */
-        btsnd_hcic_ble_set_random_addr(p_cb->private_addr);
+        btm_ble_set_random_address(p_cb->private_addr);
 
         p_cb->own_addr_type = BLE_ADDR_RANDOM;
 
@@ -356,7 +356,7 @@
 **                  address is matched to.
 **
 *******************************************************************************/
-void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK * p_cback, void *p)
+void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK * p_cback, void *p, BOOLEAN extended)
 {
     tBTM_LE_RANDOM_CB   *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
 
@@ -365,6 +365,7 @@
         p_mgnt_cb->p = p;
         p_mgnt_cb->busy = TRUE;
         memcpy(p_mgnt_cb->random_bda, random_bda, BD_ADDR_LEN);
+        p_mgnt_cb->extended = extended;
         /* start to resolve random address */
         /* check for next security record */
 
@@ -374,9 +375,9 @@
         BTM_TRACE_EVENT("%s:  %sresolved", __func__, (p_dev_rec == NULL ? "not " : ""));
         p_mgnt_cb->busy = FALSE;
 
-        (*p_cback)(p_dev_rec, p);
+        (*p_cback)(p_dev_rec, p, extended);
     } else {
-        (*p_cback)(NULL, p);
+        (*p_cback)(NULL, p, extended);
     }
 }
 #endif
@@ -463,7 +464,8 @@
         {
             * p_static_addr_type = p_dev_rec->ble.static_addr_type;
             memcpy(random_pseudo, p_dev_rec->ble.static_addr, BD_ADDR_LEN);
-            if (controller_get_interface()->supports_ble_privacy())
+            if (controller_get_interface()->supports_ble_privacy() &&
+                !controller_get_interface()->supports_ble_extended_advertisements())
                 *p_static_addr_type |= BLE_ADDR_TYPE_ID_BIT;
             return TRUE;
         }
diff --git a/stack/btm/btm_ble_bgconn.c b/stack/btm/btm_ble_bgconn.c
index 4d2e38a..3dd01bc 100644
--- a/stack/btm/btm_ble_bgconn.c
+++ b/stack/btm/btm_ble_bgconn.c
@@ -126,18 +126,32 @@
     p_inq->sfp = scan_policy;
     p_inq->scan_type = p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE ? BTM_BLE_SCAN_MODE_ACTI : p_inq->scan_type;
 
-    if (btm_cb.cmn_ble_vsc_cb.extended_scan_support == 0)
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    if (controller_get_interface()->supports_ble_extended_advertisements())
     {
-        btsnd_hcic_ble_set_scan_params(p_inq->scan_type, (UINT16)scan_interval,
-                                       (UINT16)scan_window,
-                                       btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
-                                       scan_policy);
+        btsnd_hcic_ble_set_extended_scan_params(1 /*LE 1M PHY*/, p_inq->scan_type, (UINT16)scan_interval,
+                                                (UINT16)scan_window,
+                                                (UINT16)scan_interval,
+                                                (UINT16)scan_window,
+                                                btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
+                                                BTM_BLE_DEFAULT_SFP);
     }
     else
+#endif
     {
-        btm_ble_send_extended_scan_params(p_inq->scan_type, scan_interval, scan_window,
-                                          btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
-                                          scan_policy);
+        if (btm_cb.cmn_ble_vsc_cb.extended_scan_support == 0)
+        {
+            btsnd_hcic_ble_set_scan_params(p_inq->scan_type, (UINT16)scan_interval,
+                                           (UINT16)scan_window,
+                                           btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
+                                           scan_policy);
+        }
+        else
+        {
+            btm_ble_send_extended_scan_params(p_inq->scan_type, scan_interval, scan_window,
+                                              btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
+                                              scan_policy);
+        }
     }
 }
 /*******************************************************************************
@@ -390,30 +404,61 @@
                     && controller_get_interface()->supports_ble_privacy())
             {
                 own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
-                peer_addr_type |= BLE_ADDR_TYPE_ID_BIT;
+                if (!controller_get_interface()->supports_ble_extended_advertisements())
+                {
+                    peer_addr_type |= BLE_ADDR_TYPE_ID_BIT;
+                }
             }
 #endif
-
-            if (!btsnd_hcic_ble_create_ll_conn (scan_int,  /* UINT16 scan_int      */
-                                                scan_win,    /* UINT16 scan_win      */
-                                                0x01,                   /* UINT8 white_list     */
-                                                peer_addr_type,        /* UINT8 addr_type_peer */
-                                                dummy_bda,              /* BD_ADDR bda_peer     */
-                                                own_addr_type,          /* UINT8 addr_type_own */
-                                                BTM_BLE_CONN_INT_MIN_DEF,   /* UINT16 conn_int_min  */
-                                                BTM_BLE_CONN_INT_MAX_DEF,   /* UINT16 conn_int_max  */
-                                                BTM_BLE_CONN_SLAVE_LATENCY_DEF,  /* UINT16 conn_latency  */
-                                                BTM_BLE_CONN_TIMEOUT_DEF,        /* UINT16 conn_timeout  */
-                                                0,                       /* UINT16 min_len       */
-                                                0))                      /* UINT16 max_len       */
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+            if (controller_get_interface()->supports_ble_extended_advertisements())
             {
-                /* start auto connection failed */
-                exec =  FALSE;
-                p_cb->wl_state &= ~BTM_BLE_WL_INIT;
+                if (!btsnd_hcic_ble_ext_create_ll_conn (1 /*LE 1M PHY*/, scan_int,  /* UINT16 scan_int      */
+                                                    scan_win,    /* UINT16 scan_win      */
+                                                    0x01,                   /* UINT8 white_list     */
+                                                    peer_addr_type,        /* UINT8 addr_type_peer */
+                                                    dummy_bda,              /* BD_ADDR bda_peer     */
+                                                    own_addr_type,          /* UINT8 addr_type_own */
+                                                    BTM_BLE_CONN_INT_MIN_DEF,   /* UINT16 conn_int_min  */
+                                                    BTM_BLE_CONN_INT_MAX_DEF,   /* UINT16 conn_int_max  */
+                                                    BTM_BLE_CONN_SLAVE_LATENCY_DEF,  /* UINT16 conn_latency  */
+                                                    BTM_BLE_CONN_TIMEOUT_DEF,        /* UINT16 conn_timeout  */
+                                                    0,                       /* UINT16 min_len       */
+                                                    0))                      /* UINT16 max_len       */
+                {
+                    /* start auto connection failed */
+                    exec =  FALSE;
+                    p_cb->wl_state &= ~BTM_BLE_WL_INIT;
+                }
+                else
+                {
+                    btm_ble_set_conn_st (BLE_BG_CONN);
+                }
             }
             else
+#endif
             {
-                btm_ble_set_conn_st (BLE_BG_CONN);
+                if (!btsnd_hcic_ble_create_ll_conn (scan_int,  /* UINT16 scan_int      */
+                                                    scan_win,    /* UINT16 scan_win      */
+                                                    0x01,                   /* UINT8 white_list     */
+                                                    peer_addr_type,        /* UINT8 addr_type_peer */
+                                                    dummy_bda,              /* BD_ADDR bda_peer     */
+                                                    own_addr_type,          /* UINT8 addr_type_own */
+                                                    BTM_BLE_CONN_INT_MIN_DEF,   /* UINT16 conn_int_min  */
+                                                    BTM_BLE_CONN_INT_MAX_DEF,   /* UINT16 conn_int_max  */
+                                                    BTM_BLE_CONN_SLAVE_LATENCY_DEF,  /* UINT16 conn_latency  */
+                                                    BTM_BLE_CONN_TIMEOUT_DEF,        /* UINT16 conn_timeout  */
+                                                    0,                       /* UINT16 min_len       */
+                                                    0))                      /* UINT16 max_len       */
+                {
+                    /* start auto connection failed */
+                    exec =  FALSE;
+                    p_cb->wl_state &= ~BTM_BLE_WL_INIT;
+                }
+                else
+                {
+                    btm_ble_set_conn_st (BLE_BG_CONN);
+                }
             }
         }
         else
@@ -472,27 +517,41 @@
             btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_PASS;
 
             /* Process advertising packets only from devices in the white list */
-            if (btm_cb.cmn_ble_vsc_cb.extended_scan_support == 0)
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+            if (controller_get_interface()->supports_ble_extended_advertisements())
             {
-                /* use passive scan by default */
-                if (!btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_PASS,
-                                                    scan_int,
-                                                    scan_win,
-                                                    p_cb->addr_mgnt_cb.own_addr_type,
-                                                    SP_ADV_WL))
-                {
-                    return FALSE;
-                }
+                btsnd_hcic_ble_set_extended_scan_params(1 /*LE 1M PHY*/, BTM_BLE_SCAN_MODE_PASS, scan_int,
+                                                        scan_win,
+                                                        scan_int,
+                                                        scan_win,
+                                                        p_cb->addr_mgnt_cb.own_addr_type,
+                                                        SP_ADV_WL);
             }
             else
+#endif
             {
-                if (!btm_ble_send_extended_scan_params(BTM_BLE_SCAN_MODE_PASS,
-                                                       scan_int,
-                                                       scan_win,
-                                                       p_cb->addr_mgnt_cb.own_addr_type,
-                                                       SP_ADV_WL))
+                if (btm_cb.cmn_ble_vsc_cb.extended_scan_support == 0)
                 {
-                    return FALSE;
+                    /* use passive scan by default */
+                    if (!btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_PASS,
+                                                        scan_int,
+                                                        scan_win,
+                                                        p_cb->addr_mgnt_cb.own_addr_type,
+                                                        SP_ADV_WL))
+                    {
+                        return FALSE;
+                    }
+                }
+                else
+                {
+                    if (!btm_ble_send_extended_scan_params(BTM_BLE_SCAN_MODE_PASS,
+                                                           scan_int,
+                                                           scan_win,
+                                                           p_cb->addr_mgnt_cb.own_addr_type,
+                                                           SP_ADV_WL))
+                    {
+                        return FALSE;
+                    }
                 }
             }
 
@@ -506,8 +565,18 @@
 #if BLE_PRIVACY_SPT == TRUE
                 btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN);
 #endif
-                if (!btsnd_hcic_ble_set_scan_enable(TRUE, TRUE)) /* duplicate filtering enabled */
-                     return FALSE;
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+                if (controller_get_interface()->supports_ble_extended_advertisements())
+                {
+                    if (!btsnd_hcic_ble_set_extended_scan_enable(TRUE,TRUE, 0, 0))
+                        return FALSE;
+                }
+                else
+#endif
+                {
+                    if (!btsnd_hcic_ble_set_scan_enable(TRUE, TRUE)) /* duplicate filtering enabled */
+                        return FALSE;
+                }
 
                  /* mark up inquiry status flag */
                  p_cb->scan_activity |= BTM_LE_SELECT_CONN_ACTIVE;
@@ -701,6 +770,37 @@
 }
 /*******************************************************************************
 **
+** Function         btm_ble_dequeue_direct_conn_req
+**
+** Description      This function dequeues the direct connection request
+**
+** Returns          None.
+**
+*******************************************************************************/
+void btm_ble_dequeue_direct_conn_req(BD_ADDR rem_bda)
+{
+    if (fixed_queue_is_empty(btm_cb.ble_ctr_cb.conn_pending_q))
+        return;
+
+    list_t *list = fixed_queue_get_list(btm_cb.ble_ctr_cb.conn_pending_q);
+    for (const list_node_t *node = list_begin(list); node != list_end(list);
+            node = list_next(node)) {
+        tBTM_BLE_CONN_REQ *p_req = (tBTM_BLE_CONN_REQ *)list_node(node);
+        tL2C_LCB *p_lcb = (tL2C_LCB *)p_req->p_param;
+        if ((p_lcb == NULL) || (!p_lcb->in_use)) {
+            continue;
+        }
+        //If BD address matches
+        if (!memcmp (rem_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN)) {
+            fixed_queue_try_remove_from_queue(btm_cb.ble_ctr_cb.conn_pending_q, p_req);
+            l2cu_release_lcb((tL2C_LCB *)p_req->p_param);
+            osi_free((void *)p_req);
+            break;
+        }
+    }
+}
+/*******************************************************************************
+**
 ** Function         btm_send_pending_direct_conn
 **
 ** Description      This function send the pending direct connection request in queue
diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c
index 7fe3c99..7b4e750 100644
--- a/stack/btm/btm_ble_gap.c
+++ b/stack/btm/btm_ble_gap.c
@@ -38,6 +38,7 @@
 #include "device/include/controller.h"
 #include "gap_api.h"
 #include "hcimsgs.h"
+#include "stack_config.h"
 
 #if BLE_INCLUDED == TRUE
 
@@ -46,6 +47,7 @@
 #include "gattdefs.h"
 #include "l2c_int.h"
 #include "osi/include/log.h"
+#include "osi/include/time.h"
 
 #define BTM_BLE_NAME_SHORT                  0x01
 #define BTM_BLE_NAME_CMPL                   0x02
@@ -66,13 +68,15 @@
 static tBTM_BLE_CTRL_FEATURES_CBACK    *p_ctrl_le_feature_rd_cmpl_cback = NULL;
 #endif
 
+static tBTM_BLE_CTRL_FEATURES_CBACK    *p_ext_adv_ctrl_le_feature_rd_cmpl_cback = NULL;
+
 /*******************************************************************************
 **  Local functions
 *******************************************************************************/
 static void btm_ble_update_adv_flag(UINT8 flag);
-static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt_type, UINT8 *p);
+static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT16 evt_type, UINT8 *p, BOOLEAN extended);
 UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst,
-                              tBTM_BLE_ADV_DATA *p_data);
+                              tBTM_BLE_ADV_DATA *p_data, UINT16 max_len);
 static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
                                      BD_ADDR_PTR p_peer_addr_ptr,
                                      tBLE_ADDR_TYPE *p_peer_addr_type,
@@ -352,17 +356,21 @@
 ** Returns          void
 **
 *******************************************************************************/
-tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT8 duration,
+tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT16 duration, UINT16 period,
                            tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb)
 {
     tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
     tBTM_STATUS status = BTM_WRONG_MODE;
 
-    UINT32 scan_interval = !p_inq->scan_interval ? BTM_BLE_GAP_DISC_SCAN_INT : p_inq->scan_interval;
-    UINT32 scan_window = !p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window;
+    UINT16 scan_interval = !p_inq->scan_interval ? BTM_BLE_GAP_DISC_SCAN_INT : p_inq->scan_interval;
+    UINT16 scan_window = !p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window;
 
-    BTM_TRACE_EVENT ("%s : scan_type:%d, %d, %d", __func__, btm_cb.btm_inq_vars.scan_type,
-                      p_inq->scan_interval, p_inq->scan_window);
+    p_inq->scan_duration = duration;
+    p_inq->scan_period = period;
+
+    BTM_TRACE_EVENT ("%s : scan_type:%d, scan_interval_phy1 ::%d, scan_window_phy1::%d scan_interval_phy2 ::%d, scan_window_phy2:: %d",
+                __func__, btm_cb.btm_inq_vars.scan_type,
+                scan_interval, scan_window, p_inq->scan_interval_coded, p_inq->scan_window_coded);
 
     if (!controller_get_interface()->supports_ble())
         return BTM_ILLEGAL_VALUE;
@@ -392,18 +400,32 @@
                 btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN);
             #endif
 
-            if (cmn_ble_vsc_cb.extended_scan_support == 0)
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+            if (controller_get_interface()->supports_ble_extended_advertisements())
             {
-                btsnd_hcic_ble_set_scan_params(p_inq->scan_type, (UINT16)scan_interval,
-                                               (UINT16)scan_window,
-                                               btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
-                                               BTM_BLE_DEFAULT_SFP);
+                btsnd_hcic_ble_set_extended_scan_params(p_inq->scan_phys, p_inq->scan_type, (UINT16)scan_interval,
+                                                        (UINT16)scan_window,
+                                                        p_inq->scan_interval_coded,
+                                                        p_inq->scan_window_coded,
+                                                        btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
+                                                        BTM_BLE_DEFAULT_SFP);
             }
             else
+#endif
             {
-                btm_ble_send_extended_scan_params(p_inq->scan_type, scan_interval, scan_window,
-                                                  btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
-                                                  BTM_BLE_DEFAULT_SFP);
+                if (cmn_ble_vsc_cb.extended_scan_support == 0)
+                {
+                    btsnd_hcic_ble_set_scan_params(p_inq->scan_type, (UINT16)scan_interval,
+                                                   (UINT16)scan_window,
+                                                   btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
+                                                   BTM_BLE_DEFAULT_SFP);
+                }
+                else
+                {
+                    btm_ble_send_extended_scan_params(p_inq->scan_type, scan_interval, scan_window,
+                                                      btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
+                                                      BTM_BLE_DEFAULT_SFP);
+                }
             }
 
             p_inq->scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE;
@@ -558,8 +580,13 @@
          btm_cb.cmn_ble_vsc_cb.adv_inst_max, btm_cb.cmn_ble_vsc_cb.rpa_offloading,
          btm_cb.cmn_ble_vsc_cb.energy_support, btm_cb.cmn_ble_vsc_cb.extended_scan_support);
 
-    if (BTM_BleMaxMultiAdvInstanceCount() > 0)
-        btm_ble_multi_adv_init();
+    if ((btm_cb.cmn_ble_vsc_cb.adv_inst_max > 0)
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+        &&
+        (controller_get_interface()->get_ble_adv_ext_size() == 0)
+#endif
+       )
+        btm_ble_multi_adv_init(btm_cb.cmn_ble_vsc_cb.adv_inst_max);
 
     if (btm_cb.cmn_ble_vsc_cb.max_filter > 0)
         btm_ble_adv_filter_init();
@@ -600,6 +627,25 @@
     }
 }
 
+/*******************************************************************************
+**
+** Function         BTM_BleGetAdvExtCapabilities
+**
+** Description      This function reads local LE features
+**
+** Parameters       p_cmn_vsc_cb : Locala LE capability structure
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTM_BleGetAdvExtCapabilities(tBTM_BLE_ADV_EXT_CB *p_ble_adv_ext_cb)
+{
+    BTM_TRACE_DEBUG("BTM_BleGetAdvExtCapabilities");
+
+    if (NULL != p_ble_adv_ext_cb)
+        *p_ble_adv_ext_cb = btm_cb.ble_adv_ext_cb;
+}
+
 /******************************************************************************
 **
 ** Function         BTM_BleReadControllerFeatures
@@ -634,6 +680,69 @@
     return ;
 }
 
+/******************************************************************************
+**
+** Function         BTM_BleReadExtAdvControllerFeatures
+**
+** Description      Reads BLE specific controller features
+**
+** Parameters:      tBTM_BLE_CTRL_FEATURES_CBACK : Callback to notify when features are read
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTM_BleReadExtAdvControllerFeatures(tBTM_BLE_CTRL_FEATURES_CBACK  *p_vsc_cback)
+{
+
+    BTM_TRACE_DEBUG("BTM_BleReadExtAdvControllerFeatures");
+
+    p_ext_adv_ctrl_le_feature_rd_cmpl_cback = p_vsc_cback;
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    if (controller_get_interface()->supports_ble_extended_advertisements())
+    {
+        btm_ble_extended_configure_inst_size();
+    }
+#endif
+
+    return ;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_read_inst_length_complete
+**
+** Description      This function is a callback event of read instance length
+**
+** Returns          void
+**
+*******************************************************************************/
+
+void btm_ble_read_inst_length_complete(UINT8* p, UINT16 evt_len)
+{
+    UINT8 status;
+    UINT16 inst_len;
+
+    UNUSED(evt_len);
+
+    STREAM_TO_UINT8 (status, p);
+
+    if (status != HCI_SUCCESS)
+    {
+        BTM_TRACE_ERROR ("%s, HCI command failure", __func__);
+        return;
+    }
+
+    STREAM_TO_UINT16 (inst_len, p);
+
+    BTM_TRACE_EVENT ("%s, status: %d, inst size = %d", __func__, status, inst_len);
+    btm_ble_update_multi_adv_inst_data_length(inst_len);
+
+    btm_cb.ble_adv_ext_cb.adv_inst_max = controller_get_interface()->get_ble_adv_ext_size();
+    btm_cb.ble_adv_ext_cb.adv_data_len_max = inst_len;
+    if (p_ext_adv_ctrl_le_feature_rd_cmpl_cback != NULL)
+        p_ext_adv_ctrl_le_feature_rd_cmpl_cback(status);
+}
+
 /*******************************************************************************
 **
 ** Function         BTM_BleEnableMixedPrivacyMode
@@ -724,8 +833,13 @@
 *******************************************************************************/
 extern UINT8  BTM_BleMaxMultiAdvInstanceCount(void)
 {
-    return btm_cb.cmn_ble_vsc_cb.adv_inst_max < BTM_BLE_MULTI_ADV_MAX ?
-        btm_cb.cmn_ble_vsc_cb.adv_inst_max : BTM_BLE_MULTI_ADV_MAX;
+    if (!controller_get_interface()->get_is_ready()) {
+        BTM_TRACE_ERROR("%s() controller interface not ready", __func__);
+        return 0;
+    }
+
+    return controller_get_interface()->get_ble_adv_ext_size() < BTM_BLE_MULTI_ADV_MAX ?
+        controller_get_interface()->get_ble_adv_ext_size() : BTM_BLE_MULTI_ADV_MAX;
 }
 
 #if BLE_PRIVACY_SPT == TRUE
@@ -738,17 +852,25 @@
 ** Returns          void
 **
 *******************************************************************************/
-static void btm_ble_resolve_random_addr_on_adv(void * p_rec, void *p)
+static void btm_ble_resolve_random_addr_on_adv(void * p_rec, void *p, BOOLEAN extended)
 {
     tBTM_SEC_DEV_REC    *match_rec = (tBTM_SEC_DEV_REC *) p_rec;
     UINT8       addr_type = BLE_ADDR_RANDOM;
     BD_ADDR     bda;
     UINT8       *pp = (UINT8 *)p + 1;
-    UINT8           evt_type;
+    UINT16      evt_type;
 
     BTM_TRACE_EVENT ("btm_ble_resolve_random_addr_on_adv ");
 
-    STREAM_TO_UINT8    (evt_type, pp);
+    if(extended)
+    {
+        STREAM_TO_UINT16    (evt_type, pp);
+    }
+    else
+    {
+        STREAM_TO_UINT8    (evt_type, pp);
+    }
+
     STREAM_TO_UINT8    (addr_type, pp);
     STREAM_TO_BDADDR   (bda, pp);
 
@@ -767,7 +889,7 @@
         }
     }
 
-    btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, pp);
+    btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, pp, extended);
 
     return;
 }
@@ -953,6 +1075,7 @@
     tBTM_SEC_DEV_REC *p_dev_rec;
 #endif
 
+    BTM_TRACE_EVENT ("%s connectable mode=0x%0x scan_rsp=0x%x", __FUNCTION__, p_cb->connectable_mode, p_cb->scan_rsp);
     evt_type = (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE) ? \
                 ((p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT : BTM_BLE_NON_CONNECT_EVT )\
                 : BTM_BLE_CONNECT_EVT;
@@ -1143,8 +1266,9 @@
 ** Returns          void
 **
 *******************************************************************************/
-void BTM_BleSetScanParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_window,
-                          tBLE_SCAN_MODE scan_mode,
+void BTM_BleSetScanParams(tGATT_IF client_if, UINT8 scan_phys, UINT32 scan_interval,
+                          UINT32 scan_window, UINT16 scan_interval_coded,
+                          UINT16 scan_window_coded, tBLE_SCAN_MODE scan_mode,
                           tBLE_SCAN_PARAM_SETUP_CBACK scan_setup_status_cback)
 {
     tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
@@ -1173,9 +1297,21 @@
        (scan_mode == BTM_BLE_SCAN_MODE_ACTI || scan_mode == BTM_BLE_SCAN_MODE_PASS))
     {
         p_cb->scan_type = scan_mode;
+        p_cb->scan_phys = scan_phys;
         p_cb->scan_interval = scan_interval;
         p_cb->scan_window = scan_window;
 
+        if(scan_interval_coded > 0 && scan_window_coded >0)
+        {
+            if(BTM_BLE_ISVALID_PARAM(scan_interval_coded, BTM_BLE_SCAN_INT_MIN, max_scan_interval) &&
+            BTM_BLE_ISVALID_PARAM(scan_window_coded, BTM_BLE_SCAN_WIN_MIN, max_scan_window) &&
+            (scan_mode == BTM_BLE_SCAN_MODE_ACTI || scan_mode == BTM_BLE_SCAN_MODE_PASS))
+            {
+                p_cb->scan_interval_coded = scan_interval_coded;
+                p_cb->scan_window_coded = scan_window_coded;
+            }
+        }
+
         if (scan_setup_status_cback != NULL)
             scan_setup_status_cback(client_if, BTM_SUCCESS);
     }
@@ -1212,7 +1348,7 @@
         return BTM_ILLEGAL_VALUE;
 
     memset(rsp_data, 0, BTM_BLE_AD_DATA_LEN);
-    btm_ble_build_adv_data(&data_mask, &p, p_data);
+    btm_ble_build_adv_data(&data_mask, &p, p_data, BTM_BLE_AD_DATA_LEN);
 
     if (btsnd_hcic_ble_set_scan_rsp_data((UINT8)(p - rsp_data), rsp_data))
     {
@@ -1255,7 +1391,7 @@
     p = p_cb_data->ad_data;
     p_cb_data->data_mask = data_mask;
 
-    p_cb_data->p_flags = btm_ble_build_adv_data(&mask, &p, p_data);
+    p_cb_data->p_flags = btm_ble_build_adv_data(&mask, &p, p_data, BTM_BLE_AD_DATA_LEN);
 
     p_cb_data->p_pad = p;
 
@@ -1287,7 +1423,7 @@
 ** Returns          pointer of ADV data
 **
 *******************************************************************************/
-UINT8 *BTM_CheckAdvData( UINT8 *p_adv, UINT8 type, UINT8 *p_length)
+UINT8 *BTM_CheckAdvData( UINT8 *p_adv, UINT8 type, UINT8 *p_length, UINT16 adv_data_len)
 {
     UINT8 *p = p_adv;
     UINT8 length;
@@ -1296,7 +1432,7 @@
 
     STREAM_TO_UINT8(length, p);
 
-    while ( length && (p - p_adv <= BTM_BLE_CACHE_ADV_DATA_MAX))
+    while ( length && (p - p_adv <= adv_data_len))
     {
         STREAM_TO_UINT8(adv_type, p);
 
@@ -1356,12 +1492,12 @@
 ** Description      This function is called build the adv data and rsp data.
 *******************************************************************************/
 UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst,
-                              tBTM_BLE_ADV_DATA *p_data)
+                              tBTM_BLE_ADV_DATA *p_data, UINT16 max_len)
 {
     UINT32 data_mask = *p_data_mask;
     UINT8   *p = *p_dst,
     *p_flag = NULL;
-    UINT16  len = BTM_BLE_AD_DATA_LEN, cp_len = 0;
+    UINT16  len = max_len, cp_len = 0;
     UINT8   i = 0;
     tBTM_BLE_PROP_ELEM      *p_elem;
 
@@ -1884,8 +2020,13 @@
 
     evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &peer_addr_type, &own_addr_type);
 
-    if (mode == BTM_BLE_NON_CONNECTABLE && p_cb->discoverable_mode == BTM_BLE_NON_DISCOVERABLE)
-        new_mode = BTM_BLE_ADV_DISABLE;
+    if (stack_config_get_interface()->get_pts_le_nonconn_adv_enabled())
+    {
+       if (combined_mode == BTM_BLE_ADV_STOP && p_cb->discoverable_mode == BTM_BLE_NON_DISCOVERABLE)
+            new_mode = BTM_BLE_ADV_DISABLE;
+    }
+    else if (mode == BTM_BLE_NON_CONNECTABLE && p_cb->discoverable_mode == BTM_BLE_NON_DISCOVERABLE)
+            new_mode = BTM_BLE_ADV_DISABLE;
 
     btm_ble_select_adv_interval(p_cb, evt_type, &adv_int_min, &adv_int_max);
 
@@ -1982,28 +2123,63 @@
 
     if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity))
     {
-        btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_ACTI,
-                                        BTM_BLE_LOW_LATENCY_SCAN_INT,
-                                        BTM_BLE_LOW_LATENCY_SCAN_WIN,
-                                        btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
-                                        SP_ADV_ALL);
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+        if (controller_get_interface()->supports_ble_extended_advertisements())
+        {
+            btsnd_hcic_ble_set_extended_scan_params(0x01 /*LE 1M */,BTM_BLE_SCAN_MODE_ACTI,
+                                BTM_BLE_LOW_LATENCY_SCAN_INT,
+                                BTM_BLE_LOW_LATENCY_SCAN_WIN,
+                                BTM_BLE_LOW_LATENCY_SCAN_INT,
+                                BTM_BLE_LOW_LATENCY_SCAN_WIN,
+                                btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
+                                SP_ADV_ALL);
+        }
+        else
+#endif
+        {
+            btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_ACTI,
+                                                    BTM_BLE_LOW_LATENCY_SCAN_INT,
+                                                    BTM_BLE_LOW_LATENCY_SCAN_WIN,
+                                                    btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
+                                                    SP_ADV_ALL);
+        }
 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
         /* enable IRK list */
         btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN);
 #endif
         p_ble_cb->inq_var.scan_duplicate_filter  = BTM_BLE_DUPLICATE_DISABLE;
+        p_ble_cb->inq_var.scan_duration  = 0;
+        p_ble_cb->inq_var.scan_period  = 0;
         status = btm_ble_start_scan();
     }
     else if ((p_ble_cb->inq_var.scan_interval != BTM_BLE_LOW_LATENCY_SCAN_INT) ||
             (p_ble_cb->inq_var.scan_window != BTM_BLE_LOW_LATENCY_SCAN_WIN)) {
         BTM_TRACE_DEBUG("%s, restart LE scan with low latency scan params", __FUNCTION__);
-        btsnd_hcic_ble_set_scan_enable(BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
-        btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_ACTI,
-                                        BTM_BLE_LOW_LATENCY_SCAN_INT,
-                                        BTM_BLE_LOW_LATENCY_SCAN_WIN,
-                                        btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
-                                        SP_ADV_ALL);
-        btsnd_hcic_ble_set_scan_enable(BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE);
+
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+        if (controller_get_interface()->supports_ble_extended_advertisements())
+        {
+            btsnd_hcic_ble_set_extended_scan_enable(BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE,0/*duration*/, 0/*period*/);
+            btsnd_hcic_ble_set_extended_scan_params(0x01 /*LE 1M */,BTM_BLE_SCAN_MODE_ACTI,
+                                BTM_BLE_LOW_LATENCY_SCAN_INT,
+                                BTM_BLE_LOW_LATENCY_SCAN_WIN,
+                                BTM_BLE_LOW_LATENCY_SCAN_INT,
+                                BTM_BLE_LOW_LATENCY_SCAN_WIN,
+                                btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
+                                SP_ADV_ALL);
+            btsnd_hcic_ble_set_extended_scan_enable(BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE,0/*duration*/, 0/*period*/);
+        }
+        else
+#endif
+        {
+            btsnd_hcic_ble_set_scan_enable(BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
+            btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_ACTI,
+                                           BTM_BLE_LOW_LATENCY_SCAN_INT,
+                                           BTM_BLE_LOW_LATENCY_SCAN_WIN,
+                                           btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
+                                           SP_ADV_ALL);
+            btsnd_hcic_ble_set_scan_enable(BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE);
+        }
     }
 
     if (status == BTM_CMD_STARTED)
@@ -2287,44 +2463,52 @@
 ** Returns          void
 **
 *******************************************************************************/
-BOOLEAN btm_ble_cache_adv_data(tBTM_INQ_RESULTS *p_cur, UINT8 data_len, UINT8 *p, UINT8 evt_type)
+BOOLEAN btm_ble_cache_adv_data(tBTM_INQ_RESULTS *p_cur, UINT8 data_len, UINT8 *p, UINT16 evt_type, BOOLEAN extended)
 {
-    tBTM_BLE_INQ_CB     *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var;
-    UINT8 *p_cache;
-    UINT8 length;
-    UNUSED(p_cur);
+    tBTM_BLE_INQ_DATA_CB     *p_le_inq_cb = &p_cur->inq_data;
+    UINT8 *p_adv_data_cache;
+    tBTM_BLE_INQ_CB     *p_le_adv_data_cb = &btm_cb.ble_ctr_cb.inq_var;
 
-    /* cache adv report/scan response data */
-    if (evt_type != BTM_BLE_SCAN_RSP_EVT)
+    if(p_le_inq_cb->adv_len == 0)
     {
-        p_le_inq_cb->adv_len = 0;
-        memset(p_le_inq_cb->adv_data_cache, 0, BTM_BLE_CACHE_ADV_DATA_MAX);
+        if (controller_get_interface()->supports_ble_extended_advertisements())
+        {
+            //if evt type is Extended and Complete data, then allocate 255 bytes of adv data
+            if(extended && ((evt_type & BTM_BLE_EXT_LEGACY_ADV_MASK) == 0) &&
+                    ((evt_type & BTM_BLE_EXT_ADV_EVT_DATA_MASK) == 0))
+            {
+                p_le_inq_cb->adv_data_cache = osi_calloc((sizeof(UINT8)) * (HCI_COMMAND_SIZE));
+            }
+            //if evt type is Extended and Incomplete data, then allocate controller's max supported bytes
+            else if(extended && ((evt_type & BTM_BLE_EXT_LEGACY_ADV_MASK) == 0) &&
+                    ((evt_type & BTM_BLE_EXT_ADV_EVT_DATA_INCMPL_MASK) == BTM_BLE_EXT_ADV_EVT_DATA_INCMPL_MASK))
+            {
+                p_le_inq_cb->adv_data_cache = osi_calloc(sizeof(UINT8) * (btm_cb.ble_adv_ext_cb.adv_data_len_max));
+            }
+            else
+            {
+                p_le_inq_cb->adv_data_cache = osi_calloc((sizeof(UINT8)) * (BTM_BLE_CACHE_ADV_DATA_MAX));
+            }
+        }
+        else
+            p_le_inq_cb->adv_data_cache = p_le_adv_data_cb->adv_data_cache;
     }
 
-    if (data_len > 0)
+    /* cache adv report/scan response data ,check for only legacy adv's scan rsp evt*/
+    if (((!extended && (evt_type != BTM_BLE_SCAN_RSP_EVT)) ||
+        (extended && ((evt_type & BTM_BLE_EXT_LEGACY_ADV_MASK) == BTM_BLE_EXT_LEGACY_ADV_MASK) &&
+        ((evt_type & BTM_BLE_EXT_SCAN_RSP_EVT_MASK) != BTM_BLE_EXT_SCAN_RSP_EVT_MASK))))
     {
-        p_cache = &p_le_inq_cb->adv_data_cache[p_le_inq_cb->adv_len];
-        STREAM_TO_UINT8(length, p);
-        while ( length && ((p_le_inq_cb->adv_len + length + 1) <= BTM_BLE_CACHE_ADV_DATA_MAX))
-        {
-            /* adv record size must be smaller than the total adv data size */
-            if ((length + 1) > data_len) {
-                BTM_TRACE_ERROR("BTM - got incorrect LE advertising data");
-                android_errorWriteLog(0x534e4554, "33899337");
-                return FALSE;
-            }
-            /* copy from the length byte & data into cache */
-            memcpy(p_cache, p-1, length+1);
-            /* reduce the total data size by size of data copied */
-            data_len -= length + 1;
-            /* advance the cache pointer past data */
-            p_cache += length+1;
-            /* increment cache length */
-            p_le_inq_cb->adv_len += length+1;
-            /* skip the length of data */
-            p += length;
-            STREAM_TO_UINT8(length, p);
-        }
+        p_le_inq_cb->adv_len = 0;
+        memset(p_le_inq_cb->adv_data_cache, 0, sizeof(UINT8) * (BTM_BLE_CACHE_ADV_DATA_MAX));
+    }
+
+    p_adv_data_cache = &p_le_inq_cb->adv_data_cache[p_le_inq_cb->adv_len];
+
+    if(data_len > 0)
+    {
+        p_le_inq_cb->adv_len += data_len;
+        memcpy(p_adv_data_cache, p, sizeof(UINT8) * data_len);
     }
     return TRUE;
 
@@ -2349,10 +2533,14 @@
     UINT8               *p_flag, flag = 0, rt = 0;
     UINT8                data_len;
     tBTM_INQ_PARMS      *p_cond = &btm_cb.btm_inq_vars.inqparms;
-    tBTM_BLE_INQ_CB     *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var;
+    tBTM_BLE_INQ_DATA_CB   *p_le_inq_cb;
+    tINQ_DB_ENT          *p_i;
 
     UNUSED(p);
 
+    p_i = btm_inq_db_find (bda);
+    p_le_inq_cb = &p_i->inq_info.results.inq_data;
+
     /* for observer, always "discoverable */
     if (BTM_BLE_IS_OBS_ACTIVE(btm_cb.ble_ctr_cb.scan_activity))
         rt |= BTM_BLE_OBS_RESULT;
@@ -2372,7 +2560,7 @@
     if (p_le_inq_cb->adv_len != 0)
     {
         if ((p_flag = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache,
-            BTM_BLE_AD_TYPE_FLAG, &data_len)) != NULL)
+            BTM_BLE_AD_TYPE_FLAG, &data_len, p_le_inq_cb->adv_len)) != NULL)
         {
             flag = * p_flag;
 
@@ -2523,6 +2711,39 @@
 
 /*******************************************************************************
 **
+** Function         btm_ble_is_adv_reportable
+**
+** Description      Checks whether the adv event type is reportable to upper layers.
+**
+** Parameters
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN btm_ble_is_adv_reportable(BOOLEAN extended, UINT16 evt_type)
+{
+    BOOLEAN to_report = TRUE;
+    if ((!extended && btm_cb.ble_ctr_cb.inq_var.scan_type == BTM_BLE_SCAN_MODE_ACTI &&
+        (evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_DISCOVER_EVT)) ||
+        //Legacy adv in extended adv report, update only the scan response evt
+        (extended && btm_cb.ble_ctr_cb.inq_var.scan_type == BTM_BLE_SCAN_MODE_ACTI &&
+        ((evt_type & BTM_BLE_EXT_LEGACY_ADV_MASK) == BTM_BLE_EXT_LEGACY_ADV_MASK) &&
+        ((evt_type & BTM_BLE_EXT_SCAN_RSP_EVT_MASK) != BTM_BLE_EXT_SCAN_RSP_EVT_MASK)) ||
+        /*Non Legacy adv in extended adv report, update scan rsp evt,connectable only and
+          non connectable-non scannable adv evts */
+        (extended && btm_cb.ble_ctr_cb.inq_var.scan_type == BTM_BLE_SCAN_MODE_ACTI &&
+        ((evt_type & BTM_BLE_EXT_LEGACY_ADV_MASK) == 0) &&
+        ((evt_type & BTM_BLE_EXT_SCAN_RSP_EVT_MASK) != BTM_BLE_EXT_SCAN_RSP_EVT_MASK) &&
+        ((evt_type & BTM_BLE_EXT_CONN_ADV_MASK) != BTM_BLE_EXT_CONN_ADV_MASK) &&
+        (evt_type != 0)))
+        {
+            to_report = FALSE;
+        }
+    return to_report;
+}
+
+/*******************************************************************************
+**
 ** Function         btm_ble_update_inq_result
 **
 ** Description      Update adv packet information into inquiry result.
@@ -2532,7 +2753,7 @@
 ** Returns          void
 **
 *******************************************************************************/
-BOOLEAN btm_ble_update_inq_result(tINQ_DB_ENT *p_i, UINT8 addr_type, UINT8 evt_type, UINT8 *p)
+BOOLEAN btm_ble_update_inq_result(tINQ_DB_ENT *p_i, UINT8 addr_type, UINT16 evt_type, UINT8 *p, BOOLEAN extended)
 {
     BOOLEAN             to_report = TRUE;
     tBTM_INQ_RESULTS     *p_cur = &p_i->inq_info.results;
@@ -2540,32 +2761,82 @@
     UINT8               *p_flag;
     tBTM_INQUIRY_VAR_ST  *p_inq = &btm_cb.btm_inq_vars;
     UINT8                data_len, rssi;
-    tBTM_BLE_INQ_CB     *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var;
     UINT8 *p1;
     UINT8               *p_uuid16;
+    UINT8                pri_phy, sec_phy, adv_sid, txpower, direct_addr_type;
+    UINT16               periodic_adv_int;
+    BD_ADDR              direct_bda;
+    tBTM_BLE_INQ_DATA_CB  *p_le_inq_cb = &p_cur->inq_data;
+    UINT8 *p_cache;
+    UINT8 length = 0;
+    UINT16 adv_data_size = 0;
+
+
+    BTM_TRACE_EVENT("btm_ble_update_inq_result evt_type= %d", evt_type);
+
+    if(extended)
+    {
+        STREAM_TO_UINT8 (pri_phy, p);
+        STREAM_TO_UINT8 (sec_phy, p);
+        STREAM_TO_UINT8 (adv_sid, p);
+        STREAM_TO_UINT8 (txpower, p);
+        STREAM_TO_UINT8 (rssi, p);
+        STREAM_TO_UINT16 (periodic_adv_int, p);
+        STREAM_TO_UINT8 (direct_addr_type, p);
+        STREAM_TO_BDADDR (direct_bda, p);
+    }
 
     STREAM_TO_UINT8    (data_len, p);
 
-    if (data_len > BTM_BLE_ADV_DATA_LEN_MAX)
+    if (!extended && (data_len > BTM_BLE_ADV_DATA_LEN_MAX))
     {
-        BTM_TRACE_WARNING("EIR data too long %d. discard", data_len);
+        BTM_TRACE_WARNING("EIR data too long for legacy adv %d. discard", data_len);
         return FALSE;
     }
-    if (!btm_ble_cache_adv_data(p_cur, data_len, p, evt_type)) {
+    else if (extended && (data_len >  btm_cb.ble_adv_ext_cb.adv_data_len_max))
+    {
+        BTM_TRACE_WARNING("Adv data too long for extended adv %d. discard", data_len);
         return FALSE;
     }
 
-    p1 = (p + data_len);
-    STREAM_TO_UINT8 (rssi, p1);
+    if(extended && ((evt_type & BTM_BLE_EXT_ADV_EVT_DATA_MASK) == BTM_BLE_EXT_ADV_EVT_DATA_INCMPL_TRUNC_MASK))
+    {
+        BTM_TRACE_WARNING("Adv data for extended adv is truncated:: discard");
+        p_le_inq_cb->adv_len = 0;
+        if (controller_get_interface()->supports_ble_extended_advertisements() && p_le_inq_cb->adv_data_cache)
+        {
+            osi_free_and_reset((void **)&p_le_inq_cb->adv_data_cache);
+            p_le_inq_cb->adv_data_cache = NULL;
+        }
+
+        return FALSE;
+    }
+
+    if (!btm_ble_cache_adv_data(p_cur, data_len, p, evt_type, extended))
+    {
+        return FALSE;
+    }
+
+    if(!extended)
+    {
+        p1 = (p + data_len);
+        STREAM_TO_UINT8 (rssi, p1);
+    }
 
     /* Save the info */
     p_cur->inq_result_type = BTM_INQ_RESULT_BLE;
     p_cur->ble_addr_type    = addr_type;
     p_cur->rssi = rssi;
 
+    p_cur->pri_phy = pri_phy;
+    p_cur->sec_phy = sec_phy;
+    p_cur->adv_sid = adv_sid;
+    p_cur->periodic_adv_int = periodic_adv_int;
+    p_cur->direct_addr_type = direct_addr_type;
+    memcpy(p_cur->direct_bda, direct_bda, BD_ADDR_LEN);
+
     /* active scan, always wait until get scan_rsp to report the result */
-    if ((btm_cb.ble_ctr_cb.inq_var.scan_type == BTM_BLE_SCAN_MODE_ACTI &&
-         (evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_DISCOVER_EVT)))
+    if (!btm_ble_is_adv_reportable(extended, evt_type))
     {
         BTM_TRACE_DEBUG("btm_ble_update_inq_result scan_rsp=false, to_report=false,\
                               scan_type_active=%d", btm_cb.ble_ctr_cb.inq_var.scan_type);
@@ -2580,14 +2851,38 @@
     else
         p_cur->device_type |= BT_DEVICE_TYPE_BLE;
 
-    if (evt_type != BTM_BLE_SCAN_RSP_EVT)
+    if ((!extended && evt_type != BTM_BLE_SCAN_RSP_EVT) ||
+        (extended && ((evt_type & BTM_BLE_EXT_SCAN_RSP_EVT_MASK) != BTM_BLE_EXT_SCAN_RSP_EVT_MASK)))
         p_cur->ble_evt_type     = evt_type;
 
     p_i->inq_count = p_inq->inq_counter;   /* Mark entry for current inquiry */
 
+    if(extended && ((evt_type & BTM_BLE_EXT_ADV_EVT_DATA_MASK) == BTM_BLE_EXT_ADV_EVT_DATA_INCMPL_MASK))
+        return FALSE;
+
+    /* Perform length check of each adv data */
+    if (p_le_inq_cb->adv_len > 0 && p_le_inq_cb->adv_data_cache)
+    {
+        p_cache = &p_le_inq_cb->adv_data_cache[0];
+
+        STREAM_TO_UINT8(length, p_cache);
+        while (length && ((adv_data_size + length + 1) <= p_le_inq_cb->adv_len))
+        {
+            adv_data_size += length+1;
+            p_cache += length;
+            if (adv_data_size < p_le_inq_cb->adv_len)
+            {
+                /* skip the length of data */
+                STREAM_TO_UINT8(length, p_cache);
+            }
+        }
+
+        p_le_inq_cb->adv_len = adv_data_size;
+    }
+
     if (p_le_inq_cb->adv_len != 0)
     {
-        if ((p_flag = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, BTM_BLE_AD_TYPE_FLAG, &len)) != NULL)
+        if ((p_flag = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, BTM_BLE_AD_TYPE_FLAG, &len, p_le_inq_cb->adv_len)) != NULL)
             p_cur->flag = * p_flag;
     }
 
@@ -2597,7 +2892,7 @@
          * then try to convert the appearance value to a class of device value Bluedroid can use.
          * Otherwise fall back to trying to infer if it is a HID device based on the service class.
          */
-        p_uuid16 = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, BTM_BLE_AD_TYPE_APPEARANCE, &len);
+        p_uuid16 = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, BTM_BLE_AD_TYPE_APPEARANCE, &len, p_le_inq_cb->adv_len);
         if (p_uuid16 && len == 2)
         {
             btm_ble_appearance_to_cod((UINT16)p_uuid16[0] | (p_uuid16[1] << 8), p_cur->dev_class);
@@ -2605,7 +2900,7 @@
         else
         {
             if ((p_uuid16 = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache,
-                                             BTM_BLE_AD_TYPE_16SRV_CMPL, &len)) != NULL)
+                                             BTM_BLE_AD_TYPE_16SRV_CMPL, &len, p_le_inq_cb->adv_len)) != NULL)
             {
                 UINT8 i;
                 for (i = 0; i + 2 <= len; i = i + 2)
@@ -2625,7 +2920,8 @@
 
     /* if BR/EDR not supported is not set, assume is a DUMO device */
     if ((p_cur->flag & BTM_BLE_BREDR_NOT_SPT) == 0 &&
-         evt_type != BTM_BLE_CONNECT_DIR_EVT)
+         ((!extended && evt_type != BTM_BLE_CONNECT_DIR_EVT) ||
+         (extended &&  ((evt_type & BTM_BLE_EXT_CONNECT_DIR_EVT_MASK) != BTM_BLE_EXT_CONNECT_DIR_EVT_MASK))))
     {
         if (p_cur->ble_addr_type != BLE_ADDR_RANDOM)
         {
@@ -2696,10 +2992,10 @@
     /* get the device name if exist in ADV data */
     if (data_len != 0)
     {
-        p_dev_name = BTM_CheckAdvData(p_data, BTM_BLE_AD_TYPE_NAME_CMPL, &len);
+        p_dev_name = BTM_CheckAdvData(p_data, BTM_BLE_AD_TYPE_NAME_CMPL, &len, BTM_BLE_ADV_DATA_LEN_MAX);
 
         if (p_dev_name == NULL)
-            p_dev_name = BTM_CheckAdvData(p_data, BTM_BLE_AD_TYPE_NAME_SHORT, &len);
+            p_dev_name = BTM_CheckAdvData(p_data, BTM_BLE_AD_TYPE_NAME_SHORT, &len, BTM_BLE_ADV_DATA_LEN_MAX);
 
         if (p_dev_name)
             memcpy(remname, p_dev_name, len);
@@ -2714,6 +3010,26 @@
 
 /*******************************************************************************
 **
+** Function         btm_ble_scan_timeout_evt
+**
+** Description      This function is called when adv packet report events are
+**                  received from the device. It updates the inquiry database.
+**                  If the inquiry database is full, the oldest entry is discarded.
+**
+** Parameters
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_scan_timeout_evt (void)
+{
+    BTM_TRACE_DEBUG("btm_ble_scan_timeout_evt:");
+
+}
+
+
+/*******************************************************************************
+**
 ** Function         btm_ble_process_adv_pkt
 **
 ** Description      This function is called when adv packet report events are
@@ -2725,13 +3041,15 @@
 ** Returns          void
 **
 *******************************************************************************/
-void btm_ble_process_adv_pkt (UINT8 *p_data)
+void btm_ble_process_adv_pkt (UINT8 *p_data, BOOLEAN extended)
 {
     BD_ADDR             bda;
-    UINT8               evt_type = 0, *p = p_data;
+    UINT8               *p = p_data;
     UINT8               addr_type = 0;
     UINT8               num_reports;
     UINT8               data_len;
+    UINT16              evt_type=0;
+    UINT8               *p1;
 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
     BOOLEAN             match = FALSE;
 #endif
@@ -2746,10 +3064,19 @@
     while (num_reports--)
     {
         /* Extract inquiry results */
-        STREAM_TO_UINT8    (evt_type, p);
+        if(extended)
+        {
+            STREAM_TO_UINT16    (evt_type, p);
+        }
+        else
+        {
+            STREAM_TO_UINT8    (evt_type, p);
+        }
+
         STREAM_TO_UINT8    (addr_type, p);
         STREAM_TO_BDADDR   (bda, p);
 
+        p1 = p;
 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
         /* map address to security record */
         match = btm_identity_addr_to_random_pseudo(bda, &addr_type, FALSE);
@@ -2759,16 +3086,29 @@
         /* always do RRA resolution on host */
         if (!match && BTM_BLE_IS_RESOLVE_BDA(bda))
         {
-            btm_ble_resolve_random_addr(bda, btm_ble_resolve_random_addr_on_adv, p_data);
+            btm_ble_resolve_random_addr(bda, btm_ble_resolve_random_addr_on_adv, p_data, extended);
         }
         else
 #endif
-            btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, p);
+            btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, p, extended);
 
-        STREAM_TO_UINT8(data_len, p);
-
-        /* Advance to the next event data_len + rssi byte */
-        p += data_len + 1;
+        if(num_reports)
+        {
+            if(extended)
+            {
+                p1 += 14;
+                STREAM_TO_UINT8(data_len, p1);
+                p1 += data_len;
+            }
+            else
+            {
+                STREAM_TO_UINT8(data_len, p1);
+                /* Advance to the next event data_len + rssi byte */
+                p1 += data_len + 1;
+            }
+            p = p1;
+            p_data = p1;
+        }
     }
 }
 
@@ -2784,16 +3124,18 @@
 ** Returns          void
 **
 *******************************************************************************/
-static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt_type, UINT8 *p)
+static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT16 evt_type, UINT8 *p, BOOLEAN extended)
 {
     tINQ_DB_ENT          *p_i;
     tBTM_INQUIRY_VAR_ST  *p_inq = &btm_cb.btm_inq_vars;
     tBTM_INQ_RESULTS_CB  *p_inq_results_cb = p_inq->p_inq_results_cb;
     tBTM_INQ_RESULTS_CB  *p_obs_results_cb = btm_cb.ble_ctr_cb.p_obs_results_cb;
-    tBTM_BLE_INQ_CB      *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var;
+    tBTM_BLE_INQ_DATA_CB *p_le_inq_cb;
     BOOLEAN     update = TRUE;
     UINT8       result = 0;
 
+    BTM_TRACE_EVENT("%s::bda::%02x%02x%02x%02x%02x%02x",__func__, bda[0],bda[1],bda[2],bda[3],bda[4],bda[5]);
+
     p_i = btm_inq_db_find (bda);
 
     /* Check if this address has already been processed for this inquiry */
@@ -2822,6 +3164,9 @@
     {
         if ((p_i = btm_inq_db_new (bda)) != NULL)
         {
+            p_le_inq_cb = &p_i->inq_info.results.inq_data;
+            p_le_inq_cb->adv_len = 0;
+
             p_inq->inq_cmpl_info.num_resp++;
         }
         else
@@ -2831,14 +3176,19 @@
     {
         p_inq->inq_cmpl_info.num_resp++;
     }
+    p_le_inq_cb = &p_i->inq_info.results.inq_data;
+
+    p_i->time_of_resp = time_get_os_boottime_ms();
+
     /* update the LE device information in inquiry database */
-    if (!btm_ble_update_inq_result(p_i, addr_type, evt_type, p))
+    if (!btm_ble_update_inq_result(p_i, addr_type, evt_type, p, extended))
         return;
 
+
     if ((result = btm_ble_is_discoverable(bda, evt_type, p)) == 0)
     {
-      LOG_WARN(LOG_TAG, "%s device is no longer discoverable so discarding advertising packet pkt",
-          __func__);
+        LOG_WARN(LOG_TAG, "%s device is no longer discoverable so discarding advertising packet pkt",
+                __func__);
         return;
     }
     if (!update)
@@ -2870,6 +3220,7 @@
     if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE)
     {
         if (result & BTM_BLE_SEL_CONN_RESULT)
+            //TODO might need to take care of UINT16 evt_type in this callback.
             btm_send_sel_conn_callback(bda, evt_type, p, addr_type);
         else
         {
@@ -2878,6 +3229,8 @@
     }
     else
     {
+        p_i->inq_info.results.adv_data_len = p_le_inq_cb->adv_len;
+
         if (p_inq_results_cb && (result & BTM_BLE_INQ_RESULT))
         {
             (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
@@ -2886,6 +3239,15 @@
         {
             (p_obs_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
         }
+
+        //Deallocate memory for adv data cache
+        if(controller_get_interface()->supports_ble_extended_advertisements() && p_le_inq_cb->adv_data_cache)
+        {
+            osi_free_and_reset((void **)&p_le_inq_cb->adv_data_cache);
+            p_le_inq_cb->adv_data_cache = NULL;
+        }
+
+        p_le_inq_cb->adv_len = 0;
     }
 }
 
@@ -2903,12 +3265,26 @@
     tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
     tBTM_STATUS status = BTM_CMD_STARTED;
 
+    BTM_TRACE_ERROR("btm_ble_start_scan extended scan");
     /* start scan, disable duplicate filtering */
-    if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, p_inq->scan_duplicate_filter))
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    if (controller_get_interface()->supports_ble_extended_advertisements())
     {
-        status = BTM_NO_RESOURCES;
+        if (!btsnd_hcic_ble_set_extended_scan_enable (BTM_BLE_SCAN_ENABLE, p_inq->scan_duplicate_filter, p_inq->scan_duration, p_inq->scan_period))
+        {
+            status = BTM_NO_RESOURCES;
+        }
     }
     else
+#endif
+    {
+        if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, p_inq->scan_duplicate_filter))
+        {
+            status = BTM_NO_RESOURCES;
+        }
+    }
+
+    if(status == BTM_CMD_STARTED)
     {
         if (p_inq->scan_type == BTM_BLE_SCAN_MODE_ACTI)
             btm_ble_set_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT);
@@ -2929,13 +3305,22 @@
 *******************************************************************************/
 void btm_ble_stop_scan(void)
 {
-    BTM_TRACE_EVENT ("btm_ble_stop_scan ");
+    BTM_TRACE_EVENT ("btm_ble_stop_scan");
 
     /* Clear the inquiry callback if set */
     btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
 
     /* stop discovery now */
-    btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    if (controller_get_interface()->supports_ble_extended_advertisements())
+    {
+        btsnd_hcic_ble_set_extended_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE, 0, 0);
+    }
+    else
+#endif
+    {
+        btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
+    }
 
     btm_update_scanner_filter_policy(SP_ADV_ALL);
 
@@ -2959,6 +3344,8 @@
 
     p_ble_cb->scan_activity &=  ~BTM_BLE_INQUIRY_MASK;
 
+    p_ble_cb->inq_var.scan_duration = 0;
+    p_ble_cb->inq_var.scan_period = 0;
     /* If no more scan activity, stop LE scan now */
     if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity))
         btm_ble_stop_scan();
@@ -3235,6 +3622,10 @@
                 break;
             }
         }
+        /* Set PHY for the connection to 2Mbps, no coding preference */
+        BTM_SetBlePhy(p_acl_cb->remote_addr, 0,
+                      BTM_DATA_RATE_TWO|BTM_DATA_RATE_ONE,
+                      BTM_DATA_RATE_TWO|BTM_DATA_RATE_ONE, 0);
     }
 
 }
@@ -3405,6 +3796,8 @@
     p_cb->cur_states       = 0;
     p_cb->conn_pending_q = fixed_queue_new(SIZE_MAX);
 
+    memset(&(btm_cb.ble_adv_ext_cb), 0 , sizeof(tBTM_BLE_ADV_EXT_CB));
+
     p_cb->inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
     p_cb->inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
     p_cb->inq_var.adv_chnl_map = BTM_BLE_DEFAULT_ADV_CHNL_MAP;
diff --git a/stack/btm/btm_ble_int.h b/stack/btm/btm_ble_int.h
index 3b16abb..70ee1a9 100644
--- a/stack/btm/btm_ble_int.h
+++ b/stack/btm/btm_ble_int.h
@@ -50,8 +50,11 @@
 #define BTM_BLE_NAME_REQUEST    0x40
 #define BTM_BLE_OBSERVE         0x80
 
-#define BTM_BLE_MAX_WL_ENTRY        1
-#define BTM_BLE_AD_DATA_LEN         31
+#define BTM_BLE_MAX_WL_ENTRY           1
+#define BTM_BLE_AD_DATA_LEN            31
+#define BTM_BLE_EXTENDED_AD_DATA_LEN   2000
+
+#define BTM_BLE_EXT_ADV_MAX_FRAG_NUM   20
 
 #define BTM_BLE_ENC_MASK    0x03
 
@@ -135,10 +138,15 @@
 {
     UINT16 discoverable_mode;
     UINT16 connectable_mode;
+    UINT8 scan_phys;
     UINT32 scan_window;
     UINT32 scan_interval;
+    UINT16 scan_window_coded;
+    UINT16 scan_interval_coded;
     UINT8 scan_type; /* current scan type: active or passive */
     UINT8 scan_duplicate_filter; /* duplicate filter enabled for scan */
+    UINT16 scan_duration;
+    UINT16 scan_period;
     UINT16 adv_interval_min;
     UINT16 adv_interval_max;
     tBTM_BLE_AFP afp; /* advertising filter policy */
@@ -169,7 +177,7 @@
 
 
 /* random address resolving complete callback */
-typedef void (tBTM_BLE_RESOLVE_CBACK) (void * match_rec, void *p);
+typedef void (tBTM_BLE_RESOLVE_CBACK) (void * match_rec, void *p, BOOLEAN extended);
 
 typedef void (tBTM_BLE_ADDR_CBACK) (BD_ADDR_PTR static_random, void *p);
 
@@ -183,6 +191,7 @@
     tBTM_BLE_ADDR_CBACK         *p_generate_cback;
     void                        *p;
     alarm_t                     *refresh_raddr_timer;
+    BOOLEAN                     extended;
 } tBTM_LE_RANDOM_CB;
 
 #define BTM_BLE_MAX_BG_CONN_DEV_NUM    10
@@ -217,6 +226,9 @@
 #define BTM_BLE_RL_INIT         1
 #define BTM_BLE_RL_SCAN         2
 #define BTM_BLE_RL_ADV          4
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+#define BTM_BLE_RL_EXT_ADV      8
+#endif
 typedef UINT8 tBTM_BLE_RL_STATE;
 
 /* BLE connection state */
@@ -290,6 +302,10 @@
 #define BTM_PRIVACY_MIXED   3              /* BLE privacy mixed mode, broadcom propietary mode */
 typedef UINT8 tBTM_PRIVACY_MODE;
 
+/* 2Mbps PHY support*/
+#define BTM_DATA_RATE_TWO   2
+#define BTM_DATA_RATE_ONE   1
+
 /* data length change event callback */
 typedef void (tBTM_DATA_LENGTH_CHANGE_CBACK) (UINT16 max_tx_length, UINT16 max_rx_length);
 
@@ -350,7 +366,8 @@
 
 extern void btm_ble_adv_raddr_timer_timeout(void *data);
 extern void btm_ble_refresh_raddr_timer_timeout(void *data);
-extern void btm_ble_process_adv_pkt (UINT8 *p);
+extern void btm_ble_process_adv_pkt (UINT8 *p, BOOLEAN extended);
+
 extern void btm_ble_proc_scan_rsp_rpt (UINT8 *p);
 extern tBTM_STATUS btm_ble_read_remote_name(BD_ADDR remote_bda, tBTM_INQ_INFO *p_cur, tBTM_CMPL_CB *p_cb);
 extern BOOLEAN btm_ble_cancel_remote_name(BD_ADDR remote_bda);
@@ -375,7 +392,7 @@
 extern tBTM_BLE_CONN_ST btm_ble_get_conn_st(void);
 extern void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st);
 extern UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst,
-                                     tBTM_BLE_ADV_DATA *p_data);
+                                     tBTM_BLE_ADV_DATA *p_data, UINT16 max_len);
 extern tBTM_STATUS btm_ble_start_adv(void);
 extern tBTM_STATUS btm_ble_stop_adv(void);
 extern tBTM_STATUS btm_ble_start_scan(void);
@@ -433,11 +450,12 @@
 /* direct connection utility */
 extern BOOLEAN btm_send_pending_direct_conn(void);
 extern void btm_ble_enqueue_direct_conn_req(void *p_param);
+extern void btm_ble_dequeue_direct_conn_req(BD_ADDR rem_bda);
 
 /* BLE address management */
 extern void btm_gen_resolvable_private_addr (void *p_cmd_cplt_cback);
 extern void btm_gen_non_resolvable_private_addr (tBTM_BLE_ADDR_CBACK *p_cback, void *p);
-extern void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK * p_cback, void *p);
+extern void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK * p_cback, void *p, BOOLEAN extended);
 extern void btm_gen_resolve_paddr_low(tBTM_RAND_ENC *p);
 
 /*  privacy function */
@@ -459,8 +477,18 @@
 extern void btm_ble_resolving_list_cleanup(void);
 #endif
 
+#if (defined BLE_EXTENDED_ADV_SUPPORT && BLE_EXTENDED_ADV_SUPPORT == TRUE)
+extern void btm_ble_read_inst_length_complete (UINT8* p, UINT16 evt_len);
+extern void btm_ble_adv_extension_operation_complete (UINT8* p, UINT16 hcidm);
+extern void btm_ble_adv_set_terminated_evt (UINT8* p);
+extern void btm_ble_multi_adv_enable_all(UINT8 enable);
+extern void btm_ble_scan_timeout_evt(void);
+extern void btm_ble_extended_configure_inst_size(void);
+#endif
+
+extern void btm_ble_update_multi_adv_inst_data_length (UINT16 inst_len);
 extern void btm_ble_multi_adv_configure_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst);
-extern void btm_ble_multi_adv_init(void);
+extern void btm_ble_multi_adv_init(UINT8 max_adv_inst);
 extern void* btm_ble_multi_adv_get_ref(UINT8 inst_id);
 extern void btm_ble_multi_adv_cleanup(void);
 extern void btm_ble_multi_adv_reenable(UINT8 inst_id);
@@ -473,6 +501,7 @@
 extern BOOLEAN btm_ble_topology_check(tBTM_BLE_STATE_MASK request);
 extern BOOLEAN btm_ble_clear_topology_mask(tBTM_BLE_STATE_MASK request_state);
 extern BOOLEAN btm_ble_set_topology_mask(tBTM_BLE_STATE_MASK request_state);
+extern void btm_ble_set_random_address(BD_ADDR random_bda);
 
 #if BTM_BLE_CONFORMANCE_TESTING == TRUE
 extern void btm_ble_set_no_disc_if_pair_fail (BOOLEAN disble_disc);
diff --git a/stack/btm/btm_ble_multi_adv.c b/stack/btm/btm_ble_multi_adv.c
index 5efe752..1d6840a 100644
--- a/stack/btm/btm_ble_multi_adv.c
+++ b/stack/btm/btm_ble_multi_adv.c
@@ -17,9 +17,11 @@
  ******************************************************************************/
 
 #include <string.h>
+#include <pthread.h>
 
 #include "bt_target.h"
 #include "device/include/controller.h"
+#include "stack_config.h"
 
 #if (BLE_INCLUDED == TRUE)
 #include "bt_types.h"
@@ -38,15 +40,30 @@
 #define BTM_BLE_MULTI_ADV_SET_PARAM_LEN                 24
 #define BTM_BLE_MULTI_ADV_WRITE_DATA_LEN                (BTM_BLE_AD_DATA_LEN + 3)
 #define BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN           8
+#define BTM_BLE_EXTENDED_ADV_TIMEOUT                    0x3C
 
 #define BTM_BLE_MULTI_ADV_CB_EVT_MASK   0xF0
 #define BTM_BLE_MULTI_ADV_SUBCODE_MASK  0x0F
 
+#ifdef WIPOWER_SUPPORTED
+#define WIPOWER_16_UUID_LSB 0xFE
+#define WIPOWER_16_UUID_MSB 0xFF
+static bool is_wipower_adv = false;
+#endif
+
+#define BTM_BLE_EXTENDED_LEGACY_MASK    0x10
+
 /************************************************************************************
 **  Static variables
 ************************************************************************************/
 tBTM_BLE_MULTI_ADV_CB  btm_multi_adv_cb;
 tBTM_BLE_MULTI_ADV_INST_IDX_Q btm_multi_adv_idx_q;
+pthread_mutex_t btm_multi_adv_lock = PTHREAD_MUTEX_INITIALIZER;
+tBTM_BLE_EXT_ADV_ENABLE_CB btm_ble_ext_enable_cb;
+
+#ifdef WIPOWER_SUPPORTED
+UINT8 wipower_inst_id = BTM_BLE_MULTI_ADV_DEFAULT_STD;
+#endif
 
 /************************************************************************************
 **  Externs
@@ -55,6 +72,25 @@
 extern void btm_ble_update_dmt_flag_bits(UINT8 *flag_value,
                                                const UINT16 connect_mode, const UINT16 disc_mode);
 
+static inline BOOLEAN is_btm_multi_adv_cb_valid()
+{
+    if (!btm_multi_adv_cb.p_adv_inst ||
+        !btm_multi_adv_cb.op_q.p_sub_code ||
+        !btm_multi_adv_cb.op_q.p_inst_id)
+        return FALSE;
+    else
+        return TRUE;
+}
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+/************************************************************************************
+** Local declaration
+************************************************************************************/
+static tBTM_STATUS btm_ble_extended_adv_set_params (tBTM_BLE_MULTI_ADV_INST *p_inst,
+                                             tBTM_BLE_ADV_PARAMS *p_params,
+                                             UINT8 cb_evt);
+static tBTM_STATUS btm_ble_enable_extended_adv (BOOLEAN enable, UINT8 inst_id, UINT16 duration, UINT8 max_ext_adv_evts, UINT8 cb_evt);
+#endif
+
 /*******************************************************************************
 **
 ** Function         btm_ble_multi_adv_enq_op_q
@@ -67,13 +103,15 @@
 *******************************************************************************/
 void btm_ble_multi_adv_enq_op_q(UINT8 opcode, UINT8 inst_id, UINT8 cb_evt)
 {
+    UINT8 max_adv_instance = BTM_BleMaxMultiAdvInstanceCount();
     tBTM_BLE_MULTI_ADV_OPQ  *p_op_q = &btm_multi_adv_cb.op_q;
 
     p_op_q->p_inst_id[p_op_q->next_idx] = inst_id;
 
     p_op_q->p_sub_code[p_op_q->next_idx] = (opcode |(cb_evt << 4));
 
-    p_op_q->next_idx = (p_op_q->next_idx + 1) %  BTM_BleMaxMultiAdvInstanceCount();
+    if (max_adv_instance > 0)
+       p_op_q->next_idx = (p_op_q->next_idx + 1) %  max_adv_instance;
 }
 
 /*******************************************************************************
@@ -88,13 +126,15 @@
 *******************************************************************************/
 void btm_ble_multi_adv_deq_op_q(UINT8 *p_opcode, UINT8 *p_inst_id, UINT8 *p_cb_evt)
 {
+    UINT8 max_adv_instance = BTM_BleMaxMultiAdvInstanceCount();
     tBTM_BLE_MULTI_ADV_OPQ  *p_op_q = &btm_multi_adv_cb.op_q;
 
     *p_inst_id = p_op_q->p_inst_id[p_op_q->pending_idx] & 0x7F;
     *p_cb_evt = (p_op_q->p_sub_code[p_op_q->pending_idx] >> 4);
     *p_opcode = (p_op_q->p_sub_code[p_op_q->pending_idx] & BTM_BLE_MULTI_ADV_SUBCODE_MASK);
 
-    p_op_q->pending_idx = (p_op_q->pending_idx + 1) %  BTM_BleMaxMultiAdvInstanceCount();
+    if (max_adv_instance > 0)
+       p_op_q->pending_idx = (p_op_q->pending_idx + 1) % max_adv_instance;
 }
 
 /*******************************************************************************
@@ -116,6 +156,12 @@
     tBTM_BLE_MULTI_ADV_INST *p_inst ;
     UINT8   cb_evt = 0, opcode;
 
+    if (!controller_get_interface()->get_is_ready())
+    {
+        BTM_TRACE_ERROR("btm_ble_multi_adv_vsc_cmpl_cback controller not ready. returning!");
+        return;
+    }
+
     if (len  < 2)
     {
         BTM_TRACE_ERROR("wrong length for btm_ble_multi_adv_vsc_cmpl_cback");
@@ -125,6 +171,9 @@
     STREAM_TO_UINT8(status, p);
     STREAM_TO_UINT8(subcode, p);
 
+    pthread_mutex_lock(&btm_multi_adv_lock);
+    if (!is_btm_multi_adv_cb_valid())
+        goto error;
     btm_ble_multi_adv_deq_op_q(&opcode, &inst_id, &cb_evt);
 
     BTM_TRACE_DEBUG("op_code = %02x inst_id = %d cb_evt = %02x", opcode, inst_id, cb_evt);
@@ -132,7 +181,7 @@
     if (opcode != subcode || inst_id == 0)
     {
         BTM_TRACE_ERROR("get unexpected VSC cmpl, expect: %d get: %d",subcode,opcode);
-        return;
+        goto error;
     }
 
     p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
@@ -181,6 +230,9 @@
     {
         (p_inst->p_cback)(cb_evt, inst_id, p_inst->p_ref, status);
     }
+
+error:
+    pthread_mutex_unlock(&btm_multi_adv_lock);
     return;
 }
 
@@ -339,22 +391,34 @@
 tBTM_STATUS btm_ble_multi_adv_write_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst, BD_ADDR random_addr)
 {
     UINT8           param[BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN], *pp = param;
-    tBTM_STATUS     rt;
+    tBTM_STATUS     rt = BTM_NO_RESOURCES;
 
     BTM_TRACE_EVENT ("%s-BD_ADDR:%02x-%02x-%02x-%02x-%02x-%02x,inst_id:%d",
                       __FUNCTION__, random_addr[5], random_addr[4], random_addr[3], random_addr[2],
                       random_addr[1], random_addr[0], p_inst->inst_id);
 
-    memset(param, 0, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN);
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    if (controller_get_interface()->supports_ble_extended_advertisements())
+    {
+        rt = btm_ble_add_multi_adv_rpa(random_addr, BLE_ADDR_RANDOM);
+        return rt;
+    }
+    else
+#endif
+    {
+        memset(param, 0, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN);
 
-    UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR);
-    BDADDR_TO_STREAM(pp, random_addr);
-    UINT8_TO_STREAM(pp,  p_inst->inst_id);
-
-    if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
+        UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR);
+        BDADDR_TO_STREAM(pp, random_addr);
+        UINT8_TO_STREAM(pp,  p_inst->inst_id);
+        rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
                                     BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN,
                                     param,
-                                    btm_ble_multi_adv_vsc_cmpl_cback)) == BTM_CMD_STARTED)
+                                    btm_ble_multi_adv_vsc_cmpl_cback);
+    }
+
+
+    if (rt == BTM_CMD_STARTED)
     {
         /* start a periodical timer to refresh random addr */
         /* TODO: is the above comment correct - is the timer periodical? */
@@ -380,6 +444,12 @@
 *******************************************************************************/
 void btm_ble_multi_adv_gen_rpa_cmpl(tBTM_RAND_ENC *p)
 {
+    if (!controller_get_interface()->get_is_ready())
+    {
+        BTM_TRACE_ERROR("btm_ble_multi_adv_gen_rpa_cmpl controller module is not ready!");
+        return;
+    }
+
 #if (SMP_INCLUDED == TRUE)
     tSMP_ENC    output;
     UINT8 index = 0;
@@ -405,6 +475,9 @@
         }
     }
 
+    pthread_mutex_lock(&btm_multi_adv_lock);
+    if (!is_btm_multi_adv_cb_valid())
+        goto error;
     p_inst = &(btm_multi_adv_cb.p_adv_inst[index]);
 
     BTM_TRACE_EVENT ("btm_ble_multi_adv_gen_rpa_cmpl inst_id = %d", p_inst->inst_id);
@@ -436,6 +509,8 @@
             btm_ble_multi_adv_write_rpa(p_inst, p_inst->rpa);
         }
     }
+error:
+    pthread_mutex_unlock(&btm_multi_adv_lock);
 #endif
 }
 
@@ -475,6 +550,29 @@
 
 /*******************************************************************************
 **
+** Function         btm_ble_update_multi_adv_inst_data_length
+**
+** Description      This function set the random address for the adv instance
+**
+** Parameters       advertise parameters used for this instance.
+**
+** Returns          none
+**
+*******************************************************************************/
+void btm_ble_update_multi_adv_inst_data_length (UINT16 inst_len)
+{
+    int index;
+    tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0];
+    BTM_TRACE_ERROR("btm_ble_update_multi_adv_inst_data_length inst_len:%d",inst_len);
+
+    for (index = 0; index <  BTM_BleMaxMultiAdvInstanceCount() - 1; index++, p_inst++)
+    {
+        p_inst->len = inst_len;
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         btm_ble_multi_adv_reenable
 **
 ** Description      This function re-enable adv instance upon a connection establishment.
@@ -514,7 +612,7 @@
 *******************************************************************************/
 void btm_ble_multi_adv_enb_privacy(BOOLEAN enable)
 {
-    UINT8 i;
+    int i;
     tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0];
 
     for (i = 0; i <  BTM_BleMaxMultiAdvInstanceCount() - 1; i ++, p_inst++)
@@ -527,6 +625,25 @@
     }
 }
 
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+/*******************************************************************************
+**
+** Function         btm_ble_extended_configure_inst_size
+**
+** Description      This function gathers max length of advertiement sets
+**
+** Parameters       none.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void btm_ble_extended_configure_inst_size()
+{
+    BTM_TRACE_DEBUG ("%s", __func__);
+    btsnd_hcic_ble_read_extended_max_adv_len();
+}
+#endif
+
 /*******************************************************************************
 **
 ** Function         BTM_BleEnableAdvInstance
@@ -545,13 +662,13 @@
 tBTM_STATUS BTM_BleEnableAdvInstance (tBTM_BLE_ADV_PARAMS *p_params,
                                       tBTM_BLE_MULTI_ADV_CBACK *p_cback,void *p_ref)
 {
-    UINT8 i;
+    int i;
     tBTM_STATUS rt = BTM_NO_RESOURCES;
     tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0];
 
     BTM_TRACE_EVENT("BTM_BleEnableAdvInstance called");
 
-    if (0 == btm_cb.cmn_ble_vsc_cb.adv_inst_max)
+    if (0 == BTM_BleMaxMultiAdvInstanceCount())
     {
         BTM_TRACE_ERROR("Controller does not support Multi ADV");
         return BTM_ERR_PROCESSING;
@@ -569,8 +686,18 @@
         {
             p_inst->in_use = TRUE;
             /* configure adv parameter */
-            if (p_params)
-                rt = btm_ble_multi_adv_set_params(p_inst, p_params, 0);
+            if (p_params) {
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+                if (controller_get_interface()->supports_ble_extended_advertisements())
+                {
+                    rt = btm_ble_extended_adv_set_params(p_inst, p_params, 0);
+                }
+                else
+#endif
+                {
+                    rt = btm_ble_multi_adv_set_params(p_inst, p_params, 0);
+                }
+            }
             else
                 rt = BTM_CMD_STARTED;
 
@@ -580,8 +707,22 @@
 
             if (BTM_CMD_STARTED == rt)
             {
-                if ((rt = btm_ble_enable_multi_adv (TRUE, p_inst->inst_id,
-                          BTM_BLE_MULTI_ADV_ENB_EVT)) == BTM_CMD_STARTED)
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+                if (controller_get_interface()->supports_ble_extended_advertisements()) {
+                    p_inst->in_use = FALSE;
+                    btm_ble_enable_resolving_list (BTM_BLE_RL_EXT_ADV);
+                    p_inst->in_use = TRUE;
+                    rt = btm_ble_enable_extended_adv (TRUE, p_inst->inst_id,
+                                                      p_inst->duration, p_params->max_ext_adv_evts, BTM_BLE_EXTENDED_ADV_ENB_EVT);
+                }
+                else
+#endif
+                {
+                    rt = btm_ble_enable_multi_adv (TRUE, p_inst->inst_id,
+                                                    BTM_BLE_MULTI_ADV_ENB_EVT);
+                }
+
+                if (rt == BTM_CMD_STARTED)
                 {
                     p_inst->p_cback = p_cback;
                     p_inst->p_ref   = p_ref;
@@ -616,10 +757,11 @@
 {
     tBTM_STATUS rt = BTM_ILLEGAL_VALUE;
     tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
+    UINT8 cb_evt = BTM_BLE_MULTI_ADV_PARAM_EVT;
 
     BTM_TRACE_EVENT("BTM_BleUpdateAdvInstParam called with inst_id:%d", inst_id);
 
-    if (0 == btm_cb.cmn_ble_vsc_cb.adv_inst_max)
+    if (0 == BTM_BleMaxMultiAdvInstanceCount())
     {
         BTM_TRACE_ERROR("Controller does not support Multi ADV");
         return BTM_ERR_PROCESSING;
@@ -634,11 +776,39 @@
             BTM_TRACE_DEBUG("adv instance %d is not active", inst_id);
             return BTM_WRONG_MODE;
         }
-        else
-            btm_ble_enable_multi_adv(FALSE, inst_id, 0);
+        else {
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+            if (controller_get_interface()->supports_ble_extended_advertisements())
+                btm_ble_enable_extended_adv(FALSE, inst_id, 0, 0/*p_params->max_ext_adv_evts*/, 0);
+            else
+#endif
+            {
+                btm_ble_enable_multi_adv(FALSE, inst_id, 0);
+            }
+        }
 
-        if (BTM_CMD_STARTED == btm_ble_multi_adv_set_params(p_inst, p_params, 0))
-            rt = btm_ble_enable_multi_adv(TRUE, inst_id, BTM_BLE_MULTI_ADV_PARAM_EVT);
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+        if (controller_get_interface()->supports_ble_extended_advertisements())
+        {
+            rt = btm_ble_extended_adv_set_params(p_inst, p_params, 0);
+            cb_evt = BTM_BLE_EXTENDED_ADV_PARAM_EVT;
+        }
+        else
+#endif
+        {
+            rt = btm_ble_multi_adv_set_params(p_inst, p_params, 0);
+        }
+
+        if (BTM_CMD_STARTED == rt) {
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+            if (controller_get_interface()->supports_ble_extended_advertisements())
+                rt = btm_ble_enable_extended_adv(TRUE, inst_id, p_inst->duration, p_params->max_ext_adv_evts, cb_evt);
+            else
+#endif
+            {
+                rt = btm_ble_enable_multi_adv(TRUE, inst_id, cb_evt);
+            }
+        }
     }
     return rt;
 }
@@ -659,7 +829,7 @@
 **
 *******************************************************************************/
 tBTM_STATUS BTM_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
-                                    tBTM_BLE_AD_MASK data_mask,
+                                    tBTM_BLE_AD_MASK data_mask, UINT8 frag_pref,
                                     tBTM_BLE_ADV_DATA *p_data)
 {
     UINT8       param[BTM_BLE_MULTI_ADV_WRITE_DATA_LEN], *pp = param;
@@ -670,8 +840,16 @@
     UINT8 *pp_temp = (UINT8*)(param + BTM_BLE_MULTI_ADV_WRITE_DATA_LEN -1);
     tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
 
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    if (controller_get_interface()->supports_ble_extended_advertisements())
+    {
+        return BTM_BleWriteExtendedAdvData (inst_id, is_scan_rsp, data_mask,
+                                            BTM_BLE_EXT_ADV_COMPLETE ,frag_pref, p_data);
+    }
+#endif
+
     BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
-    if (0 == cmn_ble_vsc_cb.adv_inst_max)
+    if (0 == BTM_BleMaxMultiAdvInstanceCount())
     {
         BTM_TRACE_ERROR("Controller does not support Multi ADV");
         return BTM_ERR_PROCESSING;
@@ -688,9 +866,16 @@
 
     UINT8_TO_STREAM(pp, sub_code);
     p_len = pp ++;
-    btm_ble_build_adv_data(&data_mask, &pp, p_data);
+    btm_ble_build_adv_data(&data_mask, &pp, p_data, BTM_BLE_AD_DATA_LEN);
     *p_len = (UINT8)(pp - param - 2);
     UINT8_TO_STREAM(pp_temp, inst_id);
+#ifdef WIPOWER_SUPPORTED
+    if (param[7] == WIPOWER_16_UUID_LSB && param[8] == WIPOWER_16_UUID_MSB)
+    {
+        is_wipower_adv = true;
+        wipower_inst_id = inst_id;
+    }
+#endif
 
     if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
                                     (UINT8)BTM_BLE_MULTI_ADV_WRITE_DATA_LEN,
@@ -716,29 +901,45 @@
 *******************************************************************************/
 tBTM_STATUS BTM_BleDisableAdvInstance (UINT8 inst_id)
 {
-     tBTM_STATUS rt = BTM_ILLEGAL_VALUE;
-     tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
+    tBTM_STATUS rt = BTM_ILLEGAL_VALUE;
+    tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
 
-     BTM_TRACE_EVENT("BTM_BleDisableAdvInstance with inst_id:%d", inst_id);
+    BTM_TRACE_EVENT("BTM_BleDisableAdvInstance with inst_id:%d", inst_id);
 
-     BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
+    BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
 
-     if (0 == cmn_ble_vsc_cb.adv_inst_max)
-     {
-         BTM_TRACE_ERROR("Controller does not support Multi ADV");
-         return BTM_ERR_PROCESSING;
-     }
+    if (0 == BTM_BleMaxMultiAdvInstanceCount())
+    {
+        BTM_TRACE_ERROR("Controller does not support Multi ADV");
+        return BTM_ERR_PROCESSING;
+    }
 
-     if (inst_id < BTM_BleMaxMultiAdvInstanceCount() &&
-         inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD)
-     {
-         if ((rt = btm_ble_enable_multi_adv(FALSE, inst_id, BTM_BLE_MULTI_ADV_DISABLE_EVT))
-            == BTM_CMD_STARTED)
-         {
+    if (inst_id < BTM_BleMaxMultiAdvInstanceCount() &&
+        inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD)
+    {
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+        tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
+        if (controller_get_interface()->supports_ble_extended_advertisements()) {
+            rt = btm_ble_enable_extended_adv (FALSE, inst_id,
+                                                     p_inst->duration, 0/*p_params->max_ext_adv_evts*/,
+                                                     BTM_BLE_MULTI_ADV_DISABLE_EVT);
+        }
+        else
+#endif
+        {
+            rt = btm_ble_enable_multi_adv(FALSE, inst_id, BTM_BLE_MULTI_ADV_DISABLE_EVT);
+        }
+
+        if (rt == BTM_CMD_STARTED
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+            && !controller_get_interface()->supports_ble_extended_advertisements()
+#endif
+           )
+        {
             btm_ble_multi_adv_configure_rpa(&btm_multi_adv_cb.p_adv_inst[inst_id - 1]);
             alarm_cancel(btm_multi_adv_cb.p_adv_inst[inst_id - 1].adv_raddr_timer);
-            btm_multi_adv_cb.p_adv_inst[inst_id - 1].in_use = FALSE;
-         }
+        }
+        btm_multi_adv_cb.p_adv_inst[inst_id - 1].in_use = FALSE;
      }
     return rt;
 }
@@ -784,7 +985,13 @@
             adv_inst !=  BTM_BLE_MULTI_ADV_DEFAULT_STD)
         {
             BTM_TRACE_EVENT("btm_ble_multi_adv_reenable called");
-            btm_ble_multi_adv_reenable(adv_inst);
+#ifdef WIPOWER_SUPPORTED
+            if (!(is_wipower_adv && (adv_inst == wipower_inst_id))) {
+                btm_ble_multi_adv_reenable(adv_inst);
+            }
+#else
+                btm_ble_multi_adv_reenable(adv_inst);
+#endif
         }
         /* re-enable connectibility */
         else if (adv_inst == BTM_BLE_MULTI_ADV_DEFAULT_STD)
@@ -804,39 +1011,54 @@
 **
 ** Description      This function initialize the multi adv control block.
 **
-** Parameters       None
+** Parameters       UINT8 max_adv_inst
 **
 ** Returns          void
 **
 *******************************************************************************/
-void btm_ble_multi_adv_init()
+void btm_ble_multi_adv_init(UINT8 max_adv_inst)
 {
+    BTM_TRACE_ERROR("%s: max adv instances: %d", __func__, max_adv_inst);
     UINT8 i = 0;
     memset(&btm_multi_adv_cb, 0, sizeof(tBTM_BLE_MULTI_ADV_CB));
     memset (&btm_multi_adv_idx_q,0, sizeof (tBTM_BLE_MULTI_ADV_INST_IDX_Q));
+
     btm_multi_adv_idx_q.front = -1;
     btm_multi_adv_idx_q.rear = -1;
 
-    if (btm_cb.cmn_ble_vsc_cb.adv_inst_max > 0) {
+    if (max_adv_inst > 0)
+    {
         btm_multi_adv_cb.p_adv_inst = osi_calloc(sizeof(tBTM_BLE_MULTI_ADV_INST) *
-                                                 (btm_cb.cmn_ble_vsc_cb.adv_inst_max));
+                                                 (max_adv_inst));
 
         btm_multi_adv_cb.op_q.p_sub_code = osi_calloc(sizeof(UINT8) *
-                                                      (btm_cb.cmn_ble_vsc_cb.adv_inst_max));
+                                                      (max_adv_inst));
 
         btm_multi_adv_cb.op_q.p_inst_id = osi_calloc(sizeof(UINT8) *
-                                                     (btm_cb.cmn_ble_vsc_cb.adv_inst_max));
+                                                     (max_adv_inst));
+
+        btm_ble_ext_enable_cb.set_ids = osi_calloc(sizeof(UINT8) * max_adv_inst);
+
+        btm_ble_ext_enable_cb.durations = osi_calloc(sizeof(UINT16) * max_adv_inst);
+
+        btm_ble_ext_enable_cb.max_adv_events = osi_calloc(sizeof(UINT8) * max_adv_inst);
     }
 
     /* Initialize adv instance indices and IDs. */
-    for (i = 0; i < btm_cb.cmn_ble_vsc_cb.adv_inst_max; i++) {
+    for (i = 0; i < max_adv_inst; i++) {
         btm_multi_adv_cb.p_adv_inst[i].index = i;
         btm_multi_adv_cb.p_adv_inst[i].inst_id = i + 1;
         btm_multi_adv_cb.p_adv_inst[i].adv_raddr_timer =
             alarm_new("btm_ble.adv_raddr_timer");
     }
+    controller_get_interface()->set_ble_adv_ext_size(max_adv_inst);
 
-    BTM_RegisterForVSEvents(btm_ble_multi_adv_vse_cback, TRUE);
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    if(!controller_get_interface()->supports_ble_extended_advertisements())
+#endif
+    {
+        BTM_RegisterForVSEvents(btm_ble_multi_adv_vse_cback, TRUE);
+    }
 }
 
 /*******************************************************************************
@@ -851,6 +1073,12 @@
 *******************************************************************************/
 void btm_ble_multi_adv_cleanup(void)
 {
+#ifdef WIPOWER_SUPPORTED
+    is_wipower_adv = false;
+    wipower_inst_id = BTM_BLE_MULTI_ADV_DEFAULT_STD;
+#endif
+
+    pthread_mutex_lock(&btm_multi_adv_lock);
     if (btm_multi_adv_cb.p_adv_inst) {
         for (size_t i = 0; i < btm_cb.cmn_ble_vsc_cb.adv_inst_max; i++) {
             alarm_free(btm_multi_adv_cb.p_adv_inst[i].adv_raddr_timer);
@@ -860,6 +1088,11 @@
 
     osi_free_and_reset((void **)&btm_multi_adv_cb.op_q.p_sub_code);
     osi_free_and_reset((void **)&btm_multi_adv_cb.op_q.p_inst_id);
+    osi_free_and_reset((void **)&btm_multi_adv_cb.op_q.p_inst_id);
+    osi_free_and_reset((void **)&btm_ble_ext_enable_cb.set_ids);
+    osi_free_and_reset((void **)&btm_ble_ext_enable_cb.durations);
+    osi_free_and_reset((void **)&btm_ble_ext_enable_cb.max_adv_events);
+    pthread_mutex_unlock(&btm_multi_adv_lock);
 }
 
 /*******************************************************************************
@@ -886,5 +1119,690 @@
 
     return NULL;
 }
+
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+
+/*******************************************************************************
+**
+** Function         btm_ble_enable_extended_adv
+**
+** Description      This function enables the extended adv
+**
+** Parameters       enable: enable or disable
+**                  inst_id:  adv instance ID, can not be 0
+**                  duration: duration of the adv
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_enable_extended_adv (BOOLEAN enable, UINT8 inst_id, UINT16 duration, UINT8 max_ext_adv_evts, UINT8 cb_evt)
+{
+    UINT8           enb = enable ? 1: 0;
+    tBTM_STATUS     rt;
+
+    BTM_TRACE_EVENT ("%s: enb %d, Inst ID %d, dur = %d(s)",__func__, enb,inst_id, duration);
+    inst_id = inst_id - 1;
+    duration = duration * 100; //duration is interpreted as t*10msec
+
+    if ((rt = btsnd_hcic_ble_set_extended_adv_enable (enb,
+                                    1, //Num of sets
+                                    &inst_id,
+                                    &duration,
+                                    &max_ext_adv_evts))
+                                    == BTM_CMD_STARTED)
+    {
+        btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_ENB, inst_id + 1, cb_evt);
+    }
+    return rt;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_save_extended_adv_params
+**
+** Description      This function sets the extended adv params
+**
+** Parameters       p_inst: pointer to instance variable
+**                  p_params: adv parameters
+**                  cb_evt: callback event
+**
+** Returns          status
+**
+*******************************************************************************/
+void btm_ble_save_extended_adv_params (tBTM_BLE_MULTI_ADV_INST *p_inst,UINT32 adv_int_min, UINT32 adv_int_max,
+        UINT8 own_addr_type, UINT8 pri_phy, UINT8 adv_sid ,UINT8 sec_adv_max_skip, UINT8 sec_adv_phy,
+        UINT8 scan_req_notf_enb, UINT8 channel_map, UINT8 adv_filter_policy, UINT8 tx_power)
+{
+    if(p_inst != NULL)
+    {
+        p_inst->adv_int_min = adv_int_min;
+        p_inst->adv_int_max = adv_int_max;
+        p_inst->own_addr_type = own_addr_type;
+        p_inst->pri_phy = pri_phy;
+        p_inst->adv_sid = adv_sid;
+        p_inst->sec_adv_max_skip = sec_adv_max_skip;
+        p_inst->sec_adv_phy = sec_adv_phy;
+        p_inst->scan_req_notf_enb = scan_req_notf_enb;
+        p_inst->channel_map = channel_map;
+        p_inst->adv_filter_policy = adv_filter_policy;
+        p_inst->tx_power = tx_power;
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         btm_ble_extended_adv_set_params
+**
+** Description      This function sets the extended adv params
+**
+** Parameters       p_inst: pointer to instance variable
+**                  p_params: adv parameters
+**                  cb_evt: callback event
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_extended_adv_set_params (tBTM_BLE_MULTI_ADV_INST *p_inst,
+                                             tBTM_BLE_ADV_PARAMS *p_params,
+                                             UINT8 cb_evt)
+{
+    UINT8             set_id;
+    tBTM_BLE_EXT_EVT  evt_prop = BTM_BLE_EXT_CONNECT_EVT;
+    tBTM_STATUS       rt;
+    tBLE_ADDR_TYPE    own_addr_type;
+    tBLE_ADDR_TYPE    dir_addr_type = BLE_ADDR_RANDOM;
+    UINT32            adv_int_min = 0, adv_int_max =0;
+    UINT8             adv_filter_policy = 0, tx_power =0, channel_map = 0;
+    UINT8             pri_phy = 0,sec_adv_max_skip=0, sec_adv_phy=0, adv_sid=1, scan_req_notf_enb=0;
+
+    if (!p_inst)
+    {
+        BTM_TRACE_ERROR ("%s: instance variable is null", __func__);
+        return BTM_ERR_PROCESSING;
+    }
+
+    if (0 == BTM_BleMaxMultiAdvInstanceCount())
+    {
+        BTM_TRACE_ERROR ("%s: Controller does not support extended Multi ADV", __func__);
+        return BTM_ERR_PROCESSING;
+    }
+
+    set_id = p_inst->inst_id;
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+        if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)
+        {
+            own_addr_type = BLE_ADDR_RANDOM_ID;
+        }
+        else
+#endif
+        {
+            own_addr_type = BLE_ADDR_PUBLIC;
+        }
+
+    if(p_params != NULL)
+    {
+        p_inst->duration = p_params->duration;
+        p_inst->adv_evt = p_params->adv_type;
+
+        adv_int_min = p_params->adv_int_min;
+        adv_int_max = p_params->adv_int_max;
+        //To identify that event type(adv type) parameter was read from bt_stack.conf and not sent from fwks
+        if(p_params->sec_adv_phy > 0)
+        {
+            evt_prop = p_params->adv_type;
+            pri_phy = p_params->pri_phy;
+            adv_sid = p_params->adv_sid;
+            scan_req_notf_enb =p_params->scan_req_notf_enb;
+            sec_adv_phy = p_params->sec_adv_phy;
+            sec_adv_max_skip = p_params->sec_adv_max_skip;
+        }
+        else
+        {
+            switch (p_params->adv_type)
+            {
+                case BTM_BLE_CONNECT_EVT:
+                    evt_prop = BTM_BLE_EXT_CONNECT_EVT;
+                    break;
+                case BTM_BLE_CONNECT_DIR_EVT:
+                    evt_prop = BTM_BLE_EXT_CONNECT_DIR_EVT;
+                    break;
+                case BTM_BLE_DISCOVER_EVT:
+                    evt_prop = BTM_BLE_EXT_DISCOVER_EVT;
+                    break;
+                case BTM_BLE_NON_CONNECT_EVT:
+                    evt_prop = BTM_BLE_EXT_NON_CONNECT_EVT;
+                    break;
+                case BTM_BLE_CONNECT_LO_DUTY_DIR_EVT:
+                    evt_prop = BTM_BLE_EXT_CONNECT_LO_DUTY_DIR_EVT;
+                    break;
+            }
+            pri_phy = BTM_DATA_RATE_ONE;
+            adv_sid = 0x01;
+
+        }
+        p_inst->evt_prop = evt_prop;
+
+        if (p_params->channel_map == 0 || p_params->channel_map > BTM_BLE_DEFAULT_ADV_CHNL_MAP)
+            channel_map = BTM_BLE_DEFAULT_ADV_CHNL_MAP;
+        else
+            channel_map = p_params->channel_map;
+
+        if (p_params->adv_filter_policy >= AP_SCAN_CONN_POLICY_MAX)
+            adv_filter_policy = AP_SCAN_CONN_ALL;
+        else
+            adv_filter_policy = p_params->adv_filter_policy;
+
+        if (p_params->tx_power > BTM_BLE_ADV_TX_POWER_MAX)
+            tx_power = BTM_BLE_ADV_TX_POWER_MAX;
+        else
+            tx_power = p_params->tx_power;
+
+        //save ext adv params in p_inst for reenabling adv for chained ext advs
+        btm_ble_save_extended_adv_params(p_inst, adv_int_min, adv_int_max, own_addr_type, pri_phy, adv_sid ,sec_adv_max_skip,
+                                         sec_adv_phy, scan_req_notf_enb, channel_map, adv_filter_policy,tx_power);
+    }
+    //else case is reached when adv is disabled and re enabled again for chained advs
+    else
+    {
+        evt_prop = p_inst->evt_prop;
+        adv_int_min = p_inst->adv_int_min;
+        adv_int_max =p_inst->adv_int_max;
+        channel_map =p_inst->channel_map;
+        adv_filter_policy =p_inst->adv_filter_policy;
+        tx_power=p_inst->tx_power;
+        pri_phy=p_inst->pri_phy;
+        sec_adv_max_skip=p_inst->sec_adv_max_skip;
+        sec_adv_phy =p_inst->sec_adv_phy;
+        adv_sid =p_inst->adv_sid;
+        scan_req_notf_enb=p_inst->scan_req_notf_enb;
+    }
+
+    BTM_TRACE_ERROR ("%s: evt_prop::%d, primary_phy=%d,p_params->sec_adv_max_skip=%d, p_params->sec_adv_phy=%d, p_params->adv_sid=%d, p_params->scan_req_notf_enb=%d", __func__,
+                    evt_prop, pri_phy, sec_adv_max_skip, sec_adv_phy, adv_sid, scan_req_notf_enb);
+
+    rt = btsnd_hcic_ble_set_extended_adv_params (set_id - 1, evt_prop,
+                                                 adv_int_min, adv_int_max,
+                                                 channel_map, own_addr_type,
+                                                 dir_addr_type, p_inst->rpa,
+                                                 adv_filter_policy, btm_ble_map_adv_tx_power(tx_power),
+                                                 pri_phy, sec_adv_max_skip,
+                                                 sec_adv_phy, adv_sid, scan_req_notf_enb);
+
+    if (rt == BTM_CMD_STARTED)
+    {
+        btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_PARAM, set_id, cb_evt);
+    }
+
+    return rt;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_send_ext_adv_data
+**
+** Description      This function configure a Multi-ADV instance with the specified
+**                  adv data or scan response data.
+**
+** Parameters       inst_id: adv instance ID
+**                  is_scan_rsp: is this scan response. if no, set as adv data.
+**                  data_mask: adv data mask.
+**                  p_data: pointer to the adv data structure.
+**                  operation:
+**                  0x00: Intermediate fragment
+**                  0x01: first fragment
+**                  0x02: Last fragment
+**                  0x03: complete data, ctrlr fragmentation permitted
+**                  0x04: complete data, ctrlr fragmentation not permitted
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_send_ext_adv_data (BOOLEAN is_scan_rsp, UINT8 inst_id, UINT8 operation, UINT8 frag_pref, UINT8 data_len, UINT8 *param)
+{
+    tBTM_STATUS rt;
+    UINT8 sub_code;
+    if (!is_scan_rsp)
+    {
+        rt = btsnd_hcic_ble_set_extended_adv_data(inst_id - 1,
+                                    operation,
+                                    frag_pref,
+                                    data_len,
+                                    param);
+        sub_code = BTM_BLE_MULTI_ADV_WRITE_ADV_DATA;
+    }
+    else
+    {
+        rt = btsnd_hcic_ble_set_extended_scan_rsp_data(inst_id - 1,
+                                    operation,
+                                    frag_pref,
+                                    data_len,
+                                    param);
+        sub_code = BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA;
+    }
+
+    if (rt == BTM_CMD_STARTED)
+    {
+        btm_ble_multi_adv_enq_op_q(sub_code, inst_id, BTM_BLE_MULTI_ADV_DATA_EVT);
+    }
+    return rt;
+}
+
+
+/*******************************************************************************
+**
+** Function         btm_ble_compute_frag_lens
+**
+** Description      This function configure a Multi-ADV instance with the specified
+**                  adv data or scan response data.
+**
+** Parameters       inst_id: adv instance ID
+**                  is_scan_rsp: is this scan response. if no, set as adv data.
+**                  data_mask: adv data mask.
+**                  p_data: pointer to the adv data structure.
+**                  operation:
+**                  0x00: Intermediate fragment
+**                  0x01: first fragment
+**                  0x02: Last fragment
+**                  0x03: complete data, ctrlr fragmentation permitted
+**                  0x04: complete data, ctrlr fragmentation not permitted
+**
+** Returns          status
+**
+*******************************************************************************/
+void btm_ble_compute_frag_lens (UINT16 data_len, UINT8* num_hci_cmds, UINT8 *pp_data_len)
+{
+    UINT8 index = 0;
+    *num_hci_cmds = (data_len/(HCI_COMMAND_SIZE-4));
+    for(index=0; index < *num_hci_cmds; index++)
+        pp_data_len[index] = (HCI_COMMAND_SIZE -4);
+
+    if(data_len % (HCI_COMMAND_SIZE-4))
+    {
+        pp_data_len[index] = (data_len % (HCI_COMMAND_SIZE-4));
+        (*num_hci_cmds)++;
+    }
+    BTM_TRACE_EVENT("btm_ble_compute_frag_lens::Final num_hci_cmds=%d",*num_hci_cmds);
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_get_operation
+**
+** Description      This function configure a Multi-ADV instance with the specified
+**                  adv data or scan response data.
+**
+** Parameters       inst_id: adv instance ID
+**                  is_scan_rsp: is this scan response. if no, set as adv data.
+**                  data_mask: adv data mask.
+**                  p_data: pointer to the adv data structure.
+**                  operation:
+**                  0x00: Intermediate fragment
+**                  0x01: first fragment
+**                  0x02: Last fragment
+**                  0x03: complete data, ctrlr fragmentation permitted
+**                  0x04: complete data, ctrlr fragmentation not permitted
+**
+** Returns          status
+**
+*******************************************************************************/
+UINT8 btm_ble_get_operation (UINT8 num_hci_cmds_copy, UINT8 num_hci_cmds)
+{
+    UINT8 op = 0;
+    if(num_hci_cmds_copy == num_hci_cmds)
+        op = BTM_BLE_EXT_ADV_FIRST_FRAG;
+    else if(num_hci_cmds != 1)
+        op = BTM_BLE_EXT_ADV_INT_FRAG;
+    else
+        op = BTM_BLE_EXT_ADV_LAST_FRAG;
+    return op;
+}
+
+
+/*******************************************************************************
+**
+** Function         BTM_BleWriteExtendedAdvData
+**
+** Description      This function configure a Multi-ADV instance with the specified
+**                  adv data or scan response data.
+**
+** Parameters       inst_id: adv instance ID
+**                  is_scan_rsp: is this scan response. if no, set as adv data.
+**                  data_mask: adv data mask.
+**                  p_data: pointer to the adv data structure.
+**                  operation:
+**                  0x00: Intermediate fragment
+**                  0x01: first fragment
+**                  0x02: Last fragment
+**                  0x03: complete data, ctrlr fragmentation permitted
+**                  0x04: complete data, ctrlr fragmentation not permitted
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTM_STATUS BTM_BleWriteExtendedAdvData (UINT8 inst_id, BOOLEAN is_scan_rsp,
+                                    tBTM_BLE_AD_MASK data_mask,
+                                    UINT8 operation, UINT8 frag_pref,
+                                    tBTM_BLE_ADV_DATA *p_data)
+{
+    UINT8       param[BTM_BLE_EXTENDED_AD_DATA_LEN], *pp = param, frag_data[HCI_COMMAND_SIZE-4];
+    UINT8       frag_data_len[BTM_BLE_EXT_ADV_MAX_FRAG_NUM], index=0;
+    UINT16      data_len, offset =0, j=0;
+    tBTM_STATUS rt;
+    UINT8       num_hci_cmds = 0, num_hci_cmds_copy = 0;
+    tBTM_BLE_MULTI_ADV_INST *p_inst;
+    tBTM_BLE_LOCAL_ADV_DATA *p_adv_data = &btm_cb.ble_ctr_cb.inq_var.adv_data;
+
+    if (0 == BTM_BleMaxMultiAdvInstanceCount())
+    {
+        BTM_TRACE_ERROR ("%s: Controller does not support extended Multi ADV", __func__);
+        return BTM_ERR_PROCESSING;
+    }
+    BTM_TRACE_EVENT("BTM_BleWriteExtendedAdvData");
+    if (stack_config_get_interface()->get_pts_le_nonconn_adv_enabled())
+    {
+        if (p_adv_data->p_flags != NULL)
+        {
+            p_data->flag = *(p_adv_data->p_flags);
+        }
+    }
+
+    btm_ble_update_dmt_flag_bits(&p_data->flag, btm_cb.btm_inq_vars.connectable_mode,
+                                        btm_cb.btm_inq_vars.discoverable_mode);
+
+    BTM_TRACE_EVENT("%s called with inst_id:%d", __func__, inst_id);
+    // inst_id will range from 1 to 16 max, so the below should ideally fail
+    if (inst_id > BTM_BLE_MULTI_ADV_MAX || inst_id == BTM_BLE_MULTI_ADV_DEFAULT_STD)
+        return BTM_ILLEGAL_VALUE;
+
+    p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
+
+    /* check if adv is not enabled for operations 0 to 3 */
+    if (p_inst->in_use && (operation < BTM_BLE_EXT_ADV_COMPLETE))
+    {
+        BTM_TRACE_ERROR ("%s: Illegal operation: %d while adv is enabled", __func__, operation);
+        return BTM_ILLEGAL_VALUE;
+    }
+
+    memset(param, 0, BTM_BLE_EXTENDED_AD_DATA_LEN);
+
+    if (p_inst->len == 0 || (p_inst->evt_prop & BTM_BLE_EXTENDED_LEGACY_MASK)) {
+        BTM_TRACE_ERROR("%s: using default length 31 bytes", __func__);
+        p_inst->len = BTM_BLE_AD_DATA_LEN;
+    }
+
+    btm_ble_build_adv_data(&data_mask, &pp, p_data, p_inst->len);
+    data_len = (UINT16) (pp - param);
+    BTM_TRACE_ERROR("%s: data len is %d", __func__, data_len);
+
+    if(data_len > HCI_COMMAND_SIZE)
+        btm_ble_compute_frag_lens(data_len, &num_hci_cmds, frag_data_len);
+
+    num_hci_cmds_copy = num_hci_cmds;
+
+    if(num_hci_cmds > 0)
+    {
+        //Disable advertisement
+        rt = btm_ble_enable_extended_adv (FALSE, inst_id,
+                                         p_inst->duration, 0/*p_params->max_ext_adv_evts*/,
+                                         0/*instead of BTM_BLE_MULTI_ADV_DISABLE_EVT*/);
+        p_inst->in_use = FALSE;
+
+        //set ext adv params
+        if (rt == BTM_CMD_STARTED)
+        {
+            p_inst->in_use = TRUE;
+            rt = btm_ble_extended_adv_set_params(p_inst, NULL, 0);
+        }
+
+        //set ext adv data
+        if (rt == BTM_CMD_STARTED)
+        {
+            while(num_hci_cmds)
+            {
+                memset(frag_data, 0, frag_data_len[index]);
+                BTM_TRACE_ERROR("offset =%d , index =%d ,frag_data_len[index] ::%d",offset, index, frag_data_len[index]);
+                for(j=0; j< frag_data_len[index]; j++)
+                {
+                    BTM_TRACE_ERROR("Adv data ::%02x",param[offset+j]);
+                }
+                memcpy(frag_data, (param+offset), frag_data_len[index]);
+                operation = btm_ble_get_operation(num_hci_cmds_copy, num_hci_cmds);
+                offset += frag_data_len[index];
+                rt = btm_ble_send_ext_adv_data(is_scan_rsp, inst_id, operation, frag_pref, frag_data_len[index++], frag_data);
+                num_hci_cmds--;
+            }
+        }
+        //enable ext adv
+        if (rt == BTM_CMD_STARTED)
+        {
+            rt = btm_ble_enable_extended_adv (TRUE, p_inst->inst_id, p_inst->duration, 0, 0/*instead of BTM_BLE_EXTENDED_ADV_ENB_EVT*/);
+        }
+    }
+    else
+        rt = btm_ble_send_ext_adv_data(is_scan_rsp, inst_id, operation, frag_pref, data_len, param);
+
+    return rt;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_ext_adv_reenable
+**
+** Description      This function re-enable adv instance upon a connection establishment.
+**
+** Parameters       instance id
+**
+** Returns          none.
+**
+*******************************************************************************/
+void btm_ble_ext_adv_reenable(UINT8 inst_id)
+{
+    BTM_TRACE_DEBUG("%s, instance id: %d", __func__, inst_id);
+    tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
+    //TODO: Use expired ticks instead. GKI_get_os_tick_count
+    // provides time in msec. Diff between current and start time
+    // to figure out remaining duration
+    UINT16 duration = p_inst->duration;
+
+    if (TRUE == p_inst->in_use)
+    {
+        // Verify the evt prop directed adv bit is 0
+        if (!(p_inst->evt_prop & 0x04))
+            btm_ble_enable_extended_adv (TRUE, p_inst->inst_id, duration, 0, 0);
+        else
+        {
+            //mark directed adv as disabled if adv has been stopped
+            (p_inst->p_cback)(BTM_BLE_MULTI_ADV_DISABLE_EVT,p_inst->inst_id,p_inst->p_ref,0);
+             p_inst->in_use = FALSE;
+        }
+     }
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_multi_adv_enable_all
+**
+** Description      This function enables/disables all adv instances at once
+**
+** Parameters       enable/disable
+**
+** Returns          none.
+**
+*******************************************************************************/
+void btm_ble_multi_adv_enable_all(UINT8 enable)
+{
+    BTM_TRACE_DEBUG("%s, enable = %d", __func__, enable);
+    int i;
+    tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0];
+    UINT8 enb = enable? 1:0;
+    UINT8 num_instances = 0;
+
+    for (i = 0; i <  BTM_BleMaxMultiAdvInstanceCount() - 1; i++, p_inst++)
+    {
+        if (p_inst->in_use) {
+            btm_ble_ext_enable_cb.set_ids[num_instances] = p_inst->inst_id - 1;
+            btm_ble_ext_enable_cb.durations[num_instances] = p_inst->duration * 100;
+            btm_ble_ext_enable_cb.max_adv_events[num_instances] = 0x00;
+            num_instances++;
+        }
+    }
+
+    if (num_instances == 0) return;
+
+    if (!enable)
+    {
+       if (btsnd_hcic_ble_set_extended_adv_enable(enb, 0, NULL, NULL, NULL)
+                                                   == BTM_CMD_STARTED)
+       {
+           btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_ENB, 1, 0);
+       }
+    }
+    else
+    {
+        if ((btsnd_hcic_ble_set_extended_adv_enable (enb,
+                                    num_instances,
+                                    btm_ble_ext_enable_cb.set_ids,
+                                    btm_ble_ext_enable_cb.durations,
+                                    btm_ble_ext_enable_cb.max_adv_events))
+                                    == BTM_CMD_STARTED)
+        {
+            btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_ENB, 1, 0);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_adv_set_terminated_evt
+**
+** Description      This function is a callback event when an adv set is
+**                  terminiated due to connection complete or due to duration
+**                  timeout
+**
+** Returns          void
+**
+*******************************************************************************/
+
+void btm_ble_adv_set_terminated_evt (UINT8* p)
+{
+    BTM_TRACE_EVENT("%s", __func__);
+    UINT8 status;
+    UINT8 inst_id;
+    UINT16 handle;
+    tBTM_BLE_MULTI_ADV_INST *p_inst;
+
+    STREAM_TO_UINT8(status,p);
+    STREAM_TO_UINT8(inst_id, p);
+
+    //Adjust inst_id to base 1
+    inst_id++;
+
+    STREAM_TO_UINT16(handle, p);
+    BTM_TRACE_DEBUG("%s, status = %d, inst_id = %d, handle = %x",
+                     __func__, status, inst_id, handle);
+
+    if (inst_id > BTM_BleMaxMultiAdvInstanceCount() ||
+        inst_id == BTM_BLE_MULTI_ADV_DEFAULT_STD)
+    {
+        BTM_TRACE_ERROR("%s:Invalid instance received", __func__);
+        return;
+    }
+
+    p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
+
+    if (status == BTM_BLE_EXTENDED_ADV_TIMEOUT)
+    {
+        p_inst->in_use = FALSE;
+        if (p_inst->p_cback)
+            (p_inst->p_cback)(BTM_BLE_MULTI_ADV_DISABLE_EVT,p_inst->inst_id, p_inst->p_ref, 0);
+    }
+
+    else if (status == HCI_SUCCESS)
+    {
+        btm_ble_ext_adv_reenable(inst_id);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         btm_ble_adv_extension_operation_complete
+**
+** Description      This function is a callback event of adv extension operation
+**                  including write rpa, set adv data/scan rsp data
+**
+** Returns          void
+**
+*******************************************************************************/
+
+void btm_ble_adv_extension_operation_complete(UINT8* p, UINT16 hcicmd)
+{
+    UINT8 status;
+    UINT8 cb_evt = 0, opcode;
+    UINT8 subcode = 0;
+    UINT8 inst_id;
+    tBTM_BLE_MULTI_ADV_INST *p_inst ;
+    STREAM_TO_UINT8 (status, p);
+
+    BTM_TRACE_EVENT ("%s, status: %d, opcode = %d", __func__, status, hcicmd);
+
+    if (status != HCI_SUCCESS)
+    {
+        BTM_TRACE_ERROR ("%s, HCI command failure", __func__);
+        return;
+    }
+
+    btm_ble_multi_adv_deq_op_q(&opcode, &inst_id, &cb_evt);
+
+    switch (hcicmd)
+    {
+        case HCI_BLE_WRITE_EXTENDED_ADV_RPA:
+            subcode = BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR;
+            break;
+        case HCI_BLE_WRITE_EXTENDED_ADV_DATA:
+            subcode = BTM_BLE_MULTI_ADV_WRITE_ADV_DATA;
+            break;
+        case HCI_BLE_WRITE_EXTENDED_SCAN_RSP_DATA:
+            subcode = BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA;
+            break;
+        case HCI_BLE_WRITE_EXTENDED_ADV_PARAMS:
+            subcode = BTM_BLE_MULTI_ADV_SET_PARAM;
+            break;
+        case HCI_BLE_WRITE_EXTENDED_ADV_ENABLE:
+            subcode = BTM_BLE_MULTI_ADV_ENB;
+            break;
+    }
+
+    if (opcode != subcode)
+    {
+        BTM_TRACE_ERROR("got unexpected Event, expected: %d got: %d", opcode, subcode);
+        return;
+    }
+    p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
+
+    if (cb_evt != 0 && p_inst->p_cback != NULL)
+    {
+        (p_inst->p_cback)(cb_evt, inst_id, p_inst->p_ref, status);
+    }
+    return;
+}
+
+UINT8 BTM_BleGetAvailableMAInstance ()
+{
+    int index = 0;
+    tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0];
+
+    BTM_TRACE_EVENT("BTM_BleGetAvailableMAInstance");
+
+    for (index = 0; index <  BTM_BleMaxMultiAdvInstanceCount() - 1; index++, p_inst++)
+    {
+        if (FALSE == p_inst->in_use)
+            break;
+    }
+    return index;
+}
+
+#endif
 #endif
 
diff --git a/stack/btm/btm_ble_privacy.c b/stack/btm/btm_ble_privacy.c
index c8fe541..0805d34 100644
--- a/stack/btm/btm_ble_privacy.c
+++ b/stack/btm/btm_ble_privacy.c
@@ -610,6 +610,15 @@
     if (btm_ble_suspend_bg_conn())
         p_ble_cb->suspended_rl_state |= BTM_BLE_RL_INIT;
 
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    if (controller_get_interface()->supports_ble_extended_advertisements())
+    {
+      /* Disable extended adv sets if any is enabled*/
+      p_ble_cb->suspended_rl_state |= BTM_BLE_RL_EXT_ADV;
+      btm_ble_multi_adv_enable_all(FALSE);
+    }
+#endif
+
     return TRUE;
 }
 
@@ -628,6 +637,8 @@
 {
     tBTM_BLE_CB *p_ble_cb = &btm_cb.ble_ctr_cb;
 
+    p_ble_cb->inq_var.scan_duration = 0;
+    p_ble_cb->inq_var.scan_period = 0;
     if (p_ble_cb->suspended_rl_state & BTM_BLE_RL_ADV)
         btm_ble_start_adv();
 
@@ -637,6 +648,14 @@
     if  (p_ble_cb->suspended_rl_state & BTM_BLE_RL_INIT)
         btm_ble_resume_bg_conn();
 
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    if (controller_get_interface()->supports_ble_extended_advertisements())
+    {
+      if  (p_ble_cb->suspended_rl_state & BTM_BLE_RL_EXT_ADV)
+          btm_ble_multi_adv_enable_all(TRUE);
+    }
+#endif
+
     p_ble_cb->suspended_rl_state = BTM_BLE_RL_IDLE;
 }
 
@@ -747,6 +766,61 @@
     return TRUE;
 }
 
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+/*******************************************************************************
+**
+** Function         btm_ble_add_multi_adv_rpa
+**
+** Description      This function adds a dummy rpa to the resolving list for
+**                  auto generating the mutli adv set rpa
+**
+** Parameters       peer rpa to be added, addr_type
+**
+** Returns          TRUE if device added, otherwise false
+**
+*******************************************************************************/
+BOOLEAN btm_ble_add_multi_adv_rpa(BD_ADDR bda, tBLE_ADDR_TYPE addr_type)
+{
+    BOOLEAN rt = FALSE;
+    UINT8 rl_mask = btm_cb.ble_ctr_cb.rl_state;
+    BTM_TRACE_DEBUG("%s, mask = %d", __func__, rl_mask);
+    /* if controller does not support RPA offloading or privacy 1.2, skip */
+    if (controller_get_interface()->get_ble_resolving_list_max_size() == 0) {
+        BTM_TRACE_ERROR("%s, resolving list not available", __func__);
+        return rt;
+    }
+
+    if (!controller_get_interface()->supports_ble_privacy()) {
+        BTM_TRACE_ERROR("%s, privacy not supported", __func__);
+        return rt;
+    }
+
+    if (btm_cb.ble_ctr_cb.resolving_list_avail_size == 0) {
+        BTM_TRACE_ERROR("%s, resolving list already full", __func__);
+        return rt;
+    }
+
+    if (rl_mask)
+    {
+        if (!btm_ble_disable_resolving_list (rl_mask, FALSE)) {
+            return rt;
+        }
+    }
+
+    UINT8 *local_irk = btm_cb.devcb.id_keys.irk;
+    BT_OCTET16 peer_irk = {0};
+    BTM_TRACE_DEBUG("%s:adding device to controller resolving list", __func__);
+    rt = btsnd_hcic_ble_add_device_resolving_list(addr_type, bda, peer_irk, local_irk);
+
+    if (rt)
+        btm_ble_enq_resolving_list_pending(bda, BTM_BLE_META_ADD_IRK_ENTRY);
+
+    if (rl_mask)
+        btm_ble_enable_resolving_list(rl_mask);
+    return rt;
+}
+#endif
+
 /*******************************************************************************
 **
 ** Function         btm_ble_resolving_list_load_dev
@@ -807,6 +881,12 @@
                     // use identical IRK for now
                     rt = btsnd_hcic_ble_add_device_resolving_list(p_dev_rec->ble.static_addr_type,
                               p_dev_rec->ble.static_addr, peer_irk, local_irk);
+                    if (rt && controller_get_interface()->supports_set_le_privacy_mode()) {
+                        BTM_TRACE_DEBUG("%s:adding device privacy mode", __func__);
+                        rt = btsnd_hcic_ble_set_privacy_mode(p_dev_rec->ble.static_addr_type,
+                                                             p_dev_rec->ble.static_addr,
+                                                             0x01);
+                    }
                 }
                 else
                 {
diff --git a/stack/btm/btm_dev.c b/stack/btm/btm_dev.c
index c7a0b38..8794e4e 100644
--- a/stack/btm/btm_dev.c
+++ b/stack/btm/btm_dev.c
@@ -296,6 +296,11 @@
 *******************************************************************************/
 void btm_sec_free_dev (tBTM_SEC_DEV_REC *p_dev_rec)
 {
+    p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
+    p_dev_rec->sec_flags = 0;
+    p_dev_rec->sm4 = BTM_SM4_UNKNOWN;
+    p_dev_rec->p_callback = NULL;
+
 #if BLE_INCLUDED == TRUE
     /* Clear out any saved BLE keys */
     btm_sec_clear_ble_keys (p_dev_rec);
@@ -470,7 +475,8 @@
 
             /* remove the combined record */
             list_remove(btm_cb.sec_dev_rec, p_dev_rec);
-            break;
+
+            p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
         }
 
         /* an RPA device entry is a duplicate of the target record */
@@ -484,7 +490,6 @@
                 /* remove the combined record */
                 list_remove(btm_cb.sec_dev_rec, p_dev_rec);
             }
-            break;
         }
     }
 #endif
diff --git a/stack/btm/btm_devctl.c b/stack/btm/btm_devctl.c
index 18e20b5..8105298 100644
--- a/stack/btm/btm_devctl.c
+++ b/stack/btm/btm_devctl.c
@@ -178,7 +178,15 @@
   btm_cb.ble_ctr_cb.bg_conn_type = BTM_BLE_CONN_NONE;
   btm_cb.ble_ctr_cb.p_select_cback = NULL;
   gatt_reset_bgdev_list();
-  btm_ble_multi_adv_init();
+
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+  if (controller->supports_ble() && controller->supports_ble_extended_advertisements() &&
+      controller->get_ble_adv_ext_size() > 0) {
+    // provide an extra instance to accomodate for the 0th instance
+    btm_ble_multi_adv_init(controller->get_ble_adv_ext_size() + 1);
+  }
+#endif
+
 #endif
 
   btm_pm_reset();
@@ -200,6 +208,12 @@
     btm_ble_white_list_init(controller->get_ble_white_list_size());
     l2c_link_processs_ble_num_bufs(controller->get_acl_buffer_count_ble());
   }
+
+  if(controller->supports_ble_two_mbps_rate()) {
+      /* set 2mbps Tx and Rx if supported*/
+      btsnd_hcic_ble_set_default_data_rate(0, BTM_DATA_RATE_TWO|BTM_DATA_RATE_ONE,
+                                           BTM_DATA_RATE_TWO|BTM_DATA_RATE_ONE);
+  }
 #endif
 
   BTM_SetPinType (btm_cb.cfg.pin_type, btm_cb.cfg.pin_code, btm_cb.cfg.pin_code_len);
@@ -226,6 +240,17 @@
   );
 }
 
+void BTM_HCI_Reset(void)
+{
+  /* Flush all ACL connections */
+  btm_acl_device_down();
+
+  /* Clear the callback, so application would not hang on reset */
+  btm_db_reset();
+
+  btsnd_hcic_reset(LOCAL_BR_EDR_CONTROLLER_ID);
+}
+
 /*******************************************************************************
 **
 ** Function         BTM_IsDeviceUp
@@ -426,6 +451,11 @@
         /* Nothing to do for page 2 */
         break;
 
+    /* Extended Page 3 */
+    case HCI_EXT_FEATURES_PAGE_3:
+        /* Nothing to do for page 3 */
+        break;
+
     default:
         BTM_TRACE_ERROR("btm_decode_ext_features_page page=%d unknown", page_number);
         break;
@@ -632,6 +662,58 @@
     return (p_prev);
 }
 
+
+/*******************************************************************************
+**
+** Function         BTM_Hci_Raw_Command
+**
+** Description      Send  HCI raw command to the controller.
+**
+** Returns
+**      BTM_SUCCESS         Command sent. Does not expect command complete
+**                              event. (command cmpl callback param is NULL)
+**      BTM_CMD_STARTED     Command sent. Waiting for command cmpl event.
+**
+**
+*******************************************************************************/
+tBTM_STATUS BTM_Hci_Raw_Command(UINT16 opcode, UINT8 param_len,
+                              UINT8 *p_param_buf, tBTM_RAW_CMPL_CB *p_cb)
+{
+    void *p_buf;
+#if HCI_RAW_CMD_INCLUDED == TRUE
+    tBTM_DEVCB  *p_devcb = &btm_cb.devcb;
+#endif
+
+    BTM_TRACE_EVENT ("BTM: BTM_Hci_Raw_Command: Opcode: 0x%04X, ParamLen: %i.",
+                      opcode, param_len);
+
+    /* Allocate a buffer to hold HCI command plus the callback function */
+    p_buf = osi_malloc((UINT16)(sizeof(BT_HDR) + sizeof (tBTM_CMPL_CB *) +
+                            param_len + HCIC_PREAMBLE_SIZE));
+    if (p_buf != NULL)
+    {
+        btsnd_hcic_raw_cmd (p_buf, opcode, param_len, p_param_buf, (void *)p_cb);
+
+        /* Return value */
+#if HCI_RAW_CMD_INCLUDED == TRUE
+        if (p_cb != NULL) {
+            if(p_cb != (p_devcb->p_hci_evt_cb)) {
+                p_devcb->p_hci_evt_cb = p_cb;
+            }
+            return BTM_CMD_STARTED;
+        }
+#else
+        if (p_cb != NULL)
+            return BTM_CMD_STARTED;
+#endif
+        else
+            return BTM_SUCCESS;
+    }
+    else
+        return BTM_NO_RESOURCES;
+
+}
+
 /*******************************************************************************
 **
 ** Function         BTM_VendorSpecificCommand
@@ -667,6 +749,33 @@
         return (BTM_SUCCESS);
 }
 
+#if HCI_RAW_CMD_INCLUDED == TRUE
+/*******************************************************************************
+**
+** Function         btm_hci_event
+**
+** Description      This function is called when HCI event is received
+**                  from the HCI layer.
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_hci_event(UINT8 *p, UINT8 event_code, UINT8 param_len)
+{
+    tBTM_DEVCB     *p_devcb = &btm_cb.devcb;
+    tBTM_RAW_CMPL  raw_cplt_params;
+
+    /* If there was a callback address for raw cmd complete, call it */
+    if (p_devcb->p_hci_evt_cb)
+    {
+        /* Pass paramters to the callback function */
+        raw_cplt_params.event_code = event_code;   /* Number of bytes in return info */
+        raw_cplt_params.param_len = param_len;    /* Number of bytes in return info */
+        raw_cplt_params.p_param_buf = p;
+        (p_devcb->p_hci_evt_cb) (&raw_cplt_params);  /* Call the cmd complete callback function */
+    }
+}
+#endif
 
 /*******************************************************************************
 **
diff --git a/stack/btm/btm_inq.c b/stack/btm/btm_inq.c
index d315c11..9d9a213 100644
--- a/stack/btm/btm_inq.c
+++ b/stack/btm/btm_inq.c
@@ -171,6 +171,11 @@
     BOOLEAN      cod_limited;
 
     BTM_TRACE_API ("BTM_SetDiscoverability");
+
+    /* Make sure the controller is active */
+    if (!controller_get_interface()->get_is_ready())
+        return (BTM_DEV_RESET);
+
 #if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
     if (controller_get_interface()->supports_ble())
     {
@@ -188,10 +193,6 @@
     if (inq_mode > BTM_MAX_DISCOVERABLE)
         return (BTM_ILLEGAL_VALUE);
 
-    /* Make sure the controller is active */
-    if (!controller_get_interface()->get_is_ready())
-        return (BTM_DEV_RESET);
-
     /* If the window and/or interval is '0', set to default values */
     if (!window)
         window = BTM_DEFAULT_DISC_WINDOW;
@@ -844,7 +845,17 @@
             p_inq->scan_type = INQ_GENERAL;
             p_inq->inq_active = BTM_INQUIRY_INACTIVE;
             btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
-            btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
+
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+            if (controller_get_interface()->supports_ble_extended_advertisements())
+            {
+                btsnd_hcic_ble_set_extended_scan_enable(BTM_BLE_SCAN_DISABLE,BTM_BLE_DUPLICATE_ENABLE, 0, 0);
+            }
+            else
+#endif
+            {
+                btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
+            }
         }
         else
 #endif
@@ -1993,6 +2004,10 @@
             p_cur->dev_class[2]       = dc[2];
             p_cur->clock_offset       = clock_offset  | BTM_CLOCK_OFFSET_VALID;
 
+            BTM_TRACE_WARNING ("btm_process_inq_results: BDA: %02x-%02x-%02x-%02x-%02x-%02x",
+                        bda[0], bda[1], bda[2],bda[3], bda[4], bda[5]);
+            BTM_TRACE_WARNING ("btm_process_inq_results: Dev class: %02x-%02x-%02x",
+                        p_cur->dev_class[0], p_cur->dev_class[1], p_cur->dev_class[2]);
             p_i->time_of_resp = time_get_os_boottime_ms();
 
             if (p_i->inq_count != p_inq->inq_counter)
@@ -2048,6 +2063,8 @@
             else
                 p_eir_data = NULL;
 
+            /* Set EIR data length */
+            p_cur->adv_data_len = HCI_EXT_INQ_RESPONSE_LEN;
             /* If a callback is registered, call it with the results */
             if (p_inq_results_cb)
                 (p_inq_results_cb)((tBTM_INQ_RESULTS *) p_cur, p_eir_data);
@@ -2194,7 +2211,7 @@
         if(p_inq->p_inq_ble_results_cb != NULL)
         {
             BTM_TRACE_DEBUG("BTM Inq Compl: resuming a pending LE scan");
-            BTM_BleObserve(1,0, p_inq->p_inq_ble_results_cb, p_inq->p_inq_ble_cmpl_cb);
+            BTM_BleObserve(1,0/*duration*/, 0 /*period*/, p_inq->p_inq_ble_results_cb, p_inq->p_inq_ble_cmpl_cb);
         }
 #endif
     }
@@ -2521,7 +2538,7 @@
 ** Returns          pointer of EIR data
 **
 *******************************************************************************/
-UINT8 *BTM_CheckEirData( UINT8 *p_eir, UINT8 type, UINT8 *p_length )
+UINT8 *BTM_CheckEirData( UINT8 *p_eir, UINT8 type, UINT8 *p_length, UINT16 adv_data_len )
 {
     UINT8 *p = p_eir;
     UINT8 length;
@@ -2529,7 +2546,7 @@
     BTM_TRACE_API("BTM_CheckEirData type=0x%02X", type);
 
     STREAM_TO_UINT8(length, p);
-    while( length && (p - p_eir <= HCI_EXT_INQ_RESPONSE_LEN))
+    while( length && (p - p_eir <= adv_data_len))
     {
         STREAM_TO_UINT8(eir_type, p);
         if( eir_type == type )
@@ -2826,10 +2843,10 @@
         break;
     }
 
-    p_uuid_data = BTM_CheckEirData( p_eir, complete_type, &uuid_len );
+    p_uuid_data = BTM_CheckEirData( p_eir, complete_type, &uuid_len, HCI_EXT_INQ_RESPONSE_LEN);
     if(p_uuid_data == NULL)
     {
-        p_uuid_data = BTM_CheckEirData( p_eir, more_type, &uuid_len );
+        p_uuid_data = BTM_CheckEirData( p_eir, more_type, &uuid_len, HCI_EXT_INQ_RESPONSE_LEN);
         *p_uuid_list_type = more_type;
     }
     else
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index c3357c2..d633c33 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -104,6 +104,8 @@
 #define BTM_ACL_SWKEY_STATE_ENCRYPTION_ON       4
 #define BTM_ACL_SWKEY_STATE_IN_PROGRESS         5
     UINT8           switch_role_state;
+#define BTM_MAX_SW_ROLE_FAILED_ATTEMPTS         3
+    UINT8           switch_role_failed_attempts;
 
 #define BTM_ACL_ENCRYPT_STATE_IDLE              0
 #define BTM_ACL_ENCRYPT_STATE_ENCRYPT_OFF       1   /* encryption turning off */
@@ -182,6 +184,11 @@
 
 #endif  /* BLE_INCLUDED */
 
+#if HCI_RAW_CMD_INCLUDED == TRUE
+    tBTM_RAW_CMPL_CB     *p_hci_evt_cb;       /* Callback function to be called when
+                                                HCI event is received successfully */
+#endif
+
     tBTM_IO_CAP          loc_io_caps;       /* IO capability of the local device */
     tBTM_AUTH_REQ        loc_auth_req;      /* the auth_req flag  */
     BOOLEAN              secure_connections_only;    /* Rejects service level 0 connections if */
@@ -615,6 +622,11 @@
 #define BTM_SEC_NO_LAST_SERVICE_ID      0
     UINT8           last_author_service_id;         /* ID of last serviced authorized: Reset after each l2cap connection */
 
+#if (defined(BTM_SAFE_REATTEMPT_ROLE_SWITCH) && BTM_SAFE_REATTEMPT_ROLE_SWITCH == TRUE)
+#define BTM_MAX_BL_SW_ROLE_ATTEMPTS     1
+    UINT8           switch_role_attempts;
+#endif
+
 } tBTM_SEC_DEV_REC;
 
 #define BTM_SEC_IS_SM4(sm) ((BOOLEAN)(BTM_SM4_TRUE == ((sm)&BTM_SM4_TRUE)))
@@ -819,6 +831,7 @@
     UINT16                  ediv;       /* received ediv value from LTK request */
     UINT8                   key_size;
     tBTM_BLE_VSC_CB         cmn_ble_vsc_cb;
+    tBTM_BLE_ADV_EXT_CB     ble_adv_ext_cb;
 #endif
 
                                             /* Packet types supported by the local device */
@@ -971,6 +984,7 @@
 extern tBTM_STATUS  btm_set_packet_types (tACL_CONN *p, UINT16 pkt_types);
 extern void         btm_process_clk_off_comp_evt (UINT16 hci_handle, UINT16 clock_offset);
 extern void         btm_acl_role_changed (UINT8 hci_status, BD_ADDR bd_addr, UINT8 new_role);
+extern void         btm_blacklist_role_change_device (BD_ADDR bd_addr, UINT8 hci_status);
 extern void         btm_acl_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable);
 extern UINT16       btm_get_acl_disc_reason_code (void);
 extern tBTM_STATUS  btm_remove_acl (BD_ADDR bd_addr, tBT_TRANSPORT transport);
@@ -1041,8 +1055,15 @@
 extern tBTM_STATUS btm_ble_read_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec);
 extern BOOLEAN btm_ble_resolving_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec);
 extern void btm_ble_resolving_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec);
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+extern BOOLEAN btm_ble_add_multi_adv_rpa(BD_ADDR bda, tBLE_ADDR_TYPE addr_type);
+#endif
 #endif  /* BLE_INCLUDED */
 
+/* HCI event handler */
+#if HCI_RAW_CMD_INCLUDED == TRUE
+extern void btm_hci_event(UINT8 *p, UINT8 event_code, UINT8 param_len);
+#endif
 /* Vendor Specific Command complete evt handler */
 extern void btm_vsc_complete (UINT8 *p, UINT16 cc_opcode, UINT16 evt_len,
                               tBTM_CMPL_CB *p_vsc_cplt_cback);
@@ -1077,6 +1098,8 @@
 extern tBTM_STATUS  btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_originator,
                                         UINT32 mx_proto_id, UINT32 mx_chan_id,
                                         tBTM_SEC_CALLBACK *p_callback, void *p_ref_data);
+
+extern  tBTM_STATUS btm_sec_execute_procedure (tBTM_SEC_DEV_REC *p_dev_rec);
 extern void  btm_sec_conn_req (UINT8 *bda, UINT8 *dc);
 extern void btm_create_conn_cancel_complete (UINT8 *p);
 
diff --git a/stack/btm/btm_pm.c b/stack/btm/btm_pm.c
index e24563b..986c60d 100644
--- a/stack/btm/btm_pm.c
+++ b/stack/btm/btm_pm.c
@@ -207,7 +207,7 @@
         /* check if the requested mode is supported */
         ind = mode - BTM_PM_MD_HOLD; /* make it base 0 */
         p_features = BTM_ReadLocalFeatures();
-        if( !(p_features[ btm_pm_mode_off[ind] ] & btm_pm_mode_msk[ind] ) )
+        if(ind < BTM_PM_NUM_SET_MODES && !(p_features[ btm_pm_mode_off[ind] ] & btm_pm_mode_msk[ind] ) )
             return BTM_MODE_UNSUPPORTED;
     }
 
@@ -386,7 +386,7 @@
     tBTM_PM_STATUS_CBACK *cb = NULL;
 
     /* clear the pending request for application */
-    if( (btm_cb.pm_pend_id != BTM_PM_SET_ONLY_ID) &&
+    if( (btm_cb.pm_pend_id < BTM_PM_SET_ONLY_ID) &&
         (btm_cb.pm_reg_db[btm_cb.pm_pend_id].mask & BTM_PM_REG_NOTIF) )
     {
         cb = btm_cb.pm_reg_db[btm_cb.pm_pend_id].cback;
@@ -777,10 +777,11 @@
     else /* the command was not successfull. Stay in the same state */
     {
         pm_status = BTM_PM_STS_ERROR;
+        GENERATE_VENDOR_LOGS();
     }
 
     /* notify the caller is appropriate */
-    if( (btm_cb.pm_pend_id != BTM_PM_SET_ONLY_ID) &&
+    if( (btm_cb.pm_pend_id < BTM_PM_SET_ONLY_ID) &&
         (btm_cb.pm_reg_db[btm_cb.pm_pend_id].mask & BTM_PM_REG_NOTIF) )
     {
         (*btm_cb.pm_reg_db[btm_cb.pm_pend_id].cback)(btm_cb.acl_db[btm_cb.pm_pend_link].remote_addr, pm_status, 0, status);
diff --git a/stack/btm/btm_sco.c b/stack/btm/btm_sco.c
index 4ceb640..0cc96ef 100644
--- a/stack/btm/btm_sco.c
+++ b/stack/btm/btm_sco.c
@@ -35,7 +35,8 @@
 #include "hcidefs.h"
 #include "bt_utils.h"
 #include "device/include/controller.h"
-
+#include "device/include/interop.h"
+extern void bta_dm_pm_set_sniff_policy_toggle(BD_ADDR peer_addr, BOOLEAN bDisable);
 
 #if BTM_SCO_INCLUDED == TRUE
 
@@ -641,6 +642,10 @@
                         {
                             BTM_TRACE_DEBUG("%s In sniff, park or pend mode: %d", __func__, state);
                             memset( (void*)&pm, 0, sizeof(pm));
+                            if (interop_match_addr(INTEROP_DISABLE_SNIFF_POLICY_DURING_SCO,
+                                             (const bt_bdaddr_t *)&remote_bda)) {
+                                bta_dm_pm_set_sniff_policy_toggle(remote_bda, true);
+                            }
                             pm.mode = BTM_PM_MD_ACTIVE;
                             BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, remote_bda, &pm);
                             p->state = SCO_ST_PEND_UNPARK;
@@ -708,7 +713,10 @@
                 {
                     BTM_TRACE_API("BTM_CreateSco -> (e)SCO Link for ACL handle 0x%04x, Desired Type %d",
                                     acl_handle, btm_cb.sco_cb.desired_sco_mode);
-
+                    if (interop_match_addr(INTEROP_DISABLE_SNIFF_POLICY_DURING_SCO,
+                                               (const bt_bdaddr_t *)&remote_bda)) {
+                        bta_dm_pm_set_sniff_policy_toggle(remote_bda, true);
+                    }
                     if ((btm_send_connect_request(acl_handle, p_setup)) != BTM_CMD_STARTED)
                         return (BTM_NO_RESOURCES);
 
@@ -967,12 +975,18 @@
                         BTM_TRACE_API("Role Change pending for HCI handle 0x%04x",hci_handle);
                         p->state = SCO_ST_PEND_ROLECHANGE;
                     }
-                    /* avoid calling disconnect callback because of sco creation race */
-                    else if (hci_status != HCI_ERR_LMP_ERR_TRANS_COLLISION)
-                    {
-                        p->state = SCO_ST_UNUSED;
-                        (*p->p_disc_cb)(xx);
-                    }
+
+                    /* call disconnect callback to allow SCO state machine move to proper state.
+                     * In sco creation race condition when remote rejects our sco request with
+                     * error LMP_ERR_TRANS_COLLISION and doesn't even send its request to us,
+                     * our SCO state machine remains stuck in SCO_ST_CONNECTING (BTA state machine
+                     * in SCO_OPENING_ST). We need to call SCO disconnect callback in such case
+                     * also to recover the SCO states. BTA SCO state will move to Listening after
+                     * recovery allowing further outgoing connections successfully. Any incoming
+                     * connection from remote will also be allowed.
+                     */
+                    p->state = SCO_ST_UNUSED;
+                    (*p->p_disc_cb)(xx);
                 }
                 else
                 {
@@ -1063,14 +1077,21 @@
 tBTM_STATUS BTM_RemoveSco (UINT16 sco_inx)
 {
 #if (BTM_MAX_SCO_LINKS>0)
-    tSCO_CONN   *p = &btm_cb.sco_cb.sco_db[sco_inx];
+    tSCO_CONN   *p;
     UINT16       tempstate;
     tBTM_PM_STATE   state = BTM_PM_ST_INVALID;
 
     BTM_TRACE_DEBUG("%s", __func__);
 
     /* Validity check */
-    if ((sco_inx >= BTM_MAX_SCO_LINKS) || (p->state == SCO_ST_UNUSED))
+    if (sco_inx >= BTM_MAX_SCO_LINKS)
+        return (BTM_UNKNOWN_ADDR);
+
+    /* Fix for below Klockwork Issue
+     * Array 'btm_cb.sco_cb.sco_db' of size 3 may use index value(s) 0..USHRT_MAX-1 */
+    p = &btm_cb.sco_cb.sco_db[sco_inx];
+
+    if ((p == NULL) || (p->state == SCO_ST_UNUSED))
         return (BTM_UNKNOWN_ADDR);
 
     /* If no HCI handle, simply drop the connection and return */
diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c
index 5b3a576..099d512 100644
--- a/stack/btm/btm_sec.c
+++ b/stack/btm/btm_sec.c
@@ -68,7 +68,7 @@
                                                 UINT32 mx_proto_id,
                                                 UINT32 mx_chan_id);
 
-static tBTM_STATUS btm_sec_execute_procedure (tBTM_SEC_DEV_REC *p_dev_rec);
+
 static BOOLEAN  btm_sec_start_get_name (tBTM_SEC_DEV_REC *p_dev_rec);
 static BOOLEAN  btm_sec_start_authentication (tBTM_SEC_DEV_REC *p_dev_rec);
 static BOOLEAN  btm_sec_start_encryption (tBTM_SEC_DEV_REC *p_dev_rec);
@@ -215,10 +215,12 @@
 *******************************************************************************/
 static BOOLEAN btm_serv_trusted(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_SEC_SERV_REC *p_serv_rec)
 {
-    if(BTM_SEC_IS_SERVICE_TRUSTED(p_dev_rec->trusted_mask, p_serv_rec->service_id))
+    if(p_serv_rec->service_id < BTM_SEC_MAX_SERVICES && BTM_SEC_IS_SERVICE_TRUSTED(p_dev_rec->trusted_mask, p_serv_rec->service_id))
     {
         return(TRUE);
     }
+    else
+        BTM_TRACE_ERROR("BTM_Sec: Service Id: %d not found", p_serv_rec->service_id);
     return(FALSE);
 }
 
@@ -609,7 +611,7 @@
     {
         p_srec->orig_mx_chan_id = mx_chan_id;
 #if BTM_SEC_SERVICE_NAME_LEN > 0
-        strlcpy ((char *)p_srec->orig_service_name, p_name, BTM_SEC_SERVICE_NAME_LEN);
+        strlcpy ((char *)p_srec->orig_service_name, p_name, BTM_SEC_SERVICE_NAME_LEN + 1);
 #endif
         /* clear out the old setting, just in case it exists */
 #if (L2CAP_UCD_INCLUDED == TRUE)
@@ -657,7 +659,7 @@
     {
         p_srec->term_mx_chan_id = mx_chan_id;
 #if BTM_SEC_SERVICE_NAME_LEN > 0
-        strlcpy ((char *)p_srec->term_service_name, p_name, BTM_SEC_SERVICE_NAME_LEN);
+        strlcpy ((char *)p_srec->term_service_name, p_name, BTM_SEC_SERVICE_NAME_LEN + 1);
 #endif
         /* clear out the old setting, just in case it exists */
 #if (L2CAP_UCD_INCLUDED == TRUE)
@@ -894,6 +896,7 @@
             btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
             btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;
 
+            LOG_INFO(LOG_TAG, "%s: Negative pin code reply: btm_cb.pairing_flags : %d", __func__, btm_cb.pairing_flags);
             btsnd_hcic_pin_code_neg_reply (bd_addr);
         }
         else
@@ -906,6 +909,7 @@
     if (trusted_mask)
         BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
     p_dev_rec->sec_flags   |= BTM_SEC_LINK_KEY_AUTHED;
+    p_dev_rec->pin_code_length = pin_len;
     if (pin_len >= 16) {
         p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED;
     }
@@ -916,7 +920,6 @@
     {
         /* This is start of the dedicated bonding if local device is 2.0 */
         btm_cb.pin_code_len = pin_len;
-        p_dev_rec->pin_code_length = pin_len;
         memcpy (btm_cb.pin_code, p_pin, pin_len);
 
         btm_cb.security_mode_changed = TRUE;
@@ -997,22 +1000,28 @@
     {
         return(BTM_NO_RESOURCES);
     }
-
+    if (!controller_get_interface()->get_is_ready())
+    {
+        BTM_TRACE_ERROR ("%s controller module is not ready", __func__);
+        return(BTM_NO_RESOURCES);
+    }
     BTM_TRACE_DEBUG ("before update sec_flags=0x%x", p_dev_rec->sec_flags);
 
     /* Finished if connection is active and already paired */
-    if ( ((p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE) && transport == BT_TRANSPORT_BR_EDR
+    if ((p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE) && transport == BT_TRANSPORT_BR_EDR
          &&  (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))
-#if (BLE_INCLUDED == TRUE)
-        ||((p_dev_rec->ble_hci_handle != BTM_SEC_INVALID_HANDLE) && transport == BT_TRANSPORT_LE
-         &&  (p_dev_rec->sec_flags & BTM_SEC_LE_AUTHENTICATED))
-#endif
-
-         )
     {
         BTM_TRACE_WARNING("BTM_SecBond -> Already Paired");
         return(BTM_SUCCESS);
     }
+#if (BLE_INCLUDED == TRUE)
+    if ((p_dev_rec->ble_hci_handle != BTM_SEC_INVALID_HANDLE) && transport == BT_TRANSPORT_LE
+         &&  (p_dev_rec->sec_flags & BTM_SEC_LE_AUTHENTICATED))
+    {
+        BTM_TRACE_WARNING("BTM_SecBond. Last Pairing still in progress. Wait!");
+        return(BTM_CMD_STARTED);
+    }
+#endif
 
     /* Tell controller to get rid of the link key if it has one stored */
     if ((BTM_DeleteStoredLinkKey (bd_addr, NULL)) != BTM_SUCCESS)
@@ -1546,8 +1555,10 @@
         if (res == BTM_SUCCESS)
         {
             if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL)
+            {
                 p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED;
                 p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED;
+            }
         }
 
         btsnd_hcic_user_conf_reply (bd_addr, TRUE);
@@ -2417,7 +2428,7 @@
             p_dev_rec->sec_state         = BTM_SEC_STATE_DELAY_FOR_ENC;
             (*p_callback) (bd_addr, transport, p_ref_data, rc);
 
-            return BTM_SUCCESS;
+            return BTM_CMD_STARTED;
         }
     }
 
@@ -3006,6 +3017,7 @@
     if (p_lcb && (p_lcb->link_state == LST_CONNECTED || p_lcb->link_state == LST_CONNECTING))
     {
        BTM_TRACE_WARNING("%s Connection already exists", __func__);
+       btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_PIN_REQ);
        return BTM_CMD_STARTED;
     }
 
@@ -3184,7 +3196,12 @@
                 return;
             }
 
-            if (status != HCI_SUCCESS)
+            if (status == HCI_ERR_CONTROLLER_BUSY)
+            {
+                BTM_TRACE_WARNING ("btm_sec_rmt_name_request_complete() Wait for incoming connection");
+                return;
+            }
+            else if (status != HCI_SUCCESS)
             {
                 btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
 
@@ -3456,6 +3473,7 @@
 Event uninit_use_in_call: Using uninitialized element of array "evt_data.bd_addr" in call to function "memcmp"
 False-positive: evt_data.bd_addr is set at the beginning with:     STREAM_TO_BDADDR (evt_data.bd_addr, p);
 */
+        LOG_INFO(LOG_TAG, "%s: btsnd_hcic_io_cap_req_neg_reply: err_code : %d" , __func__, err_code);
         btsnd_hcic_io_cap_req_neg_reply(evt_data.bd_addr, err_code);
         return;
     }
@@ -3472,12 +3490,12 @@
             if (btm_cb.security_mode == BTM_SEC_MODE_SC)
             {
                 /* SC only mode device requires MITM protection */
-                evt_data.auth_req = BTM_AUTH_SP_YES;
+                evt_data.auth_req = BTM_AUTH_SPGB_YES;
             }
             else
             {
                 evt_data.auth_req = (p_dev_rec->p_cur_service->security_flags &
-                                     BTM_SEC_OUT_MITM)? BTM_AUTH_SP_YES : BTM_AUTH_SP_NO;
+                                     BTM_SEC_OUT_MITM)? BTM_AUTH_SPGB_YES : BTM_AUTH_SPGB_NO;
             }
         }
     }
@@ -4031,8 +4049,23 @@
     }
 
     if (!p_dev_rec)
-        return;
+    {
+        /* check if the handle is BTM_INVALID_HCI_HANDLE */
+        if(handle == BTM_INVALID_HCI_HANDLE)
+        {
+            /* get the device with auth type as BTM_SEC_STATE_AUTHENTICATING */
+            p_dev_rec = btm_sec_find_dev_by_sec_state(BTM_SEC_STATE_AUTHENTICATING);
 
+            if ( p_dev_rec && (btm_cb.api.p_auth_complete_callback))
+            {
+                (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
+                        p_dev_rec->dev_class,
+                        p_dev_rec->sec_bd_name, status);
+                BTM_TRACE_DEBUG("btm_sec_auth_complete: Invalid Handle, send Auth failure");
+            }
+        }
+        return;
+    }
     /* keep the old sm4 flag and clear the retry bit in control block */
     old_sm4 = p_dev_rec->sm4;
     p_dev_rec->sm4 &= ~BTM_SM4_RETRY;
@@ -4074,8 +4107,13 @@
     /* User probably Disabled the keyboard while it was asleap.  Let her try */
     if (btm_cb.api.p_auth_complete_callback)
     {
-        /* report the suthentication status */
-        if (old_state != BTM_PAIR_STATE_IDLE)
+
+        /* don't post auth status key missing,peer user disc and connection timeout cases */
+        if ((old_state != BTM_PAIR_STATE_IDLE) ||
+            ((status != HCI_SUCCESS) &&
+             (status != HCI_ERR_PEER_USER) &&
+             (status != HCI_ERR_CONNECTION_TOUT) &&
+             (status != HCI_ERR_LMP_RESPONSE_TIMEOUT)))
             (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
                                                     p_dev_rec->dev_class,
                                                     p_dev_rec->sec_bd_name, status);
@@ -4105,12 +4143,10 @@
             {
                 BTM_TRACE_DEBUG ("link encrypted afer dedic bonding can use SMP_BR_CHNL");
 
-                if (btm_sec_is_master(p_dev_rec))
-                {
-                    // Encryption is required to start SM over BR/EDR
-                    // indicate that this is encryption after authentication
-                    BTM_SetEncryption(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR, NULL, NULL, 0);
-                }
+                // Encryption is required to start SM over BR/EDR
+                // from DD bonding initiator.
+                // indicate that this is encryption after authentication
+                BTM_SetEncryption(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR, NULL, NULL, 0);
             }
             l2cu_start_post_bond_timer (p_dev_rec->hci_handle);
         }
@@ -4151,6 +4187,11 @@
             }
         }
 
+        if (btm_cb.api.p_auth_complete_callback && (status == HCI_ERR_KEY_MISSING))
+            (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
+                                                    p_dev_rec->dev_class,
+                                                    p_dev_rec->sec_bd_name, status);
+
         btm_sec_dev_rec_cback_event (p_dev_rec, BTM_ERR_PROCESSING, FALSE);
 
         if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_DISC_WHEN_DONE)
@@ -4249,11 +4290,16 @@
 
     if (p_acl && p_acl->transport == BT_TRANSPORT_LE)
     {
-        if (status == HCI_ERR_KEY_MISSING || status == HCI_ERR_AUTH_FAILURE ||
+        if (status == HCI_ERR_AUTH_FAILURE ||
             status == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE)
         {
             p_dev_rec->sec_flags &= ~ (BTM_SEC_LE_LINK_KEY_KNOWN);
             p_dev_rec->ble.key_type = BTM_LE_KEY_NONE;
+            GENERATE_VENDOR_LOGS();
+        }
+        else if (status == HCI_ERR_KEY_MISSING)
+        {
+            btm_sec_disconnect(handle, status);
         }
         btm_ble_link_encrypted(p_dev_rec->ble.pseudo_addr, encr_enable);
         return;
@@ -4309,6 +4355,7 @@
 
                 BTM_TRACE_DEBUG("updated link key type to %d", p_dev_rec->link_key_type);
                 btm_send_link_key_notif(p_dev_rec);
+                GENERATE_VENDOR_LOGS();
             }
         }
     }
@@ -4359,6 +4406,7 @@
 
     BTM_TRACE_EVENT("%s", __func__);
     btm_cb.p_collided_dev_rec = 0;
+    btm_cb.collision_start_time = 0;
 
     if (btm_sec_dd_create_conn(p_dev_rec) != BTM_CMD_STARTED)
     {
@@ -4390,6 +4438,7 @@
     BOOLEAN          is_pairing_device = FALSE;
     tACL_CONN        *p_acl_cb;
     UINT8            bit_shift = 0;
+    BTM_TRACE_DEBUG ("%s",__func__);
 
     btm_acl_resubmit_page();
 
@@ -4398,10 +4447,10 @@
 #if (BT_USE_TRACES == TRUE)
     if (p_dev_rec)
     {
-        BTM_TRACE_EVENT ("Security Manager: btm_sec_connected in state: %s  handle:%d status:%d enc_mode:%d  bda:%x RName:%s",
+        BTM_TRACE_EVENT ("Security Manager: btm_sec_connected in state: %s  handle:%d status:%d enc_mode:%d  bda:%x RName:%s,new_encr_key_256 to %d",
                           btm_pair_state_descr(btm_cb.pairing_state), handle, status, enc_mode,
                           (bda[2]<<24)+(bda[3]<<16)+(bda[4]<<8)+bda[5],
-                          p_dev_rec->sec_bd_name);
+                          p_dev_rec->sec_bd_name,p_dev_rec->new_encryption_key_is_p256);
     }
     else
     {
@@ -4526,7 +4575,7 @@
             return;
         }
         /* wait for incoming connection without resetting pairing state */
-        else if (status == HCI_ERR_CONNECTION_EXISTS)
+        else if ((status == HCI_ERR_CONNECTION_EXISTS) || (status ==  HCI_ERR_CONTROLLER_BUSY))
         {
             BTM_TRACE_WARNING ("Security Manager: btm_sec_connected: Wait for incoming connection");
             return;
@@ -4568,7 +4617,6 @@
                  (((status == HCI_ERR_AUTH_FAILURE)                      ||
                  (status == HCI_ERR_KEY_MISSING)                         ||
                  (status == HCI_ERR_HOST_REJECT_SECURITY)                ||
-                 (status == HCI_ERR_PAIRING_NOT_ALLOWED)                 ||
                  (status == HCI_ERR_UNIT_KEY_USED)                       ||
                  (status == HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED) ||
                  (status == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE)           ||
@@ -4593,6 +4641,14 @@
                                                         p_dev_rec->sec_bd_name, status);
             }
         }
+        /*as p_auth_complete_callback may remove p_de_rec from list, so we
+         * need find it again */
+        p_dev_rec = btm_find_dev_by_handle (handle);
+        if(p_dev_rec == NULL)
+        {
+            BTM_TRACE_ERROR("%s p_dev_rec have been removed, return", __func__);
+            return;
+        }
 
         if (status == HCI_ERR_CONNECTION_TOUT || status == HCI_ERR_LMP_RESPONSE_TIMEOUT  ||
             status == HCI_ERR_UNSPECIFIED     || status == HCI_ERR_PAGE_TIMEOUT)
@@ -4682,12 +4738,7 @@
     /* After connection is established we perform security if we do not know */
     /* the name, or if we are originator because some procedure can have */
     /* been scheduled while connection was down */
-    BTM_TRACE_DEBUG ("is_originator:%d ", p_dev_rec->is_originator);
-    if (!(p_dev_rec->sec_flags & BTM_SEC_NAME_KNOWN) || p_dev_rec->is_originator)
-    {
-        if ((res = btm_sec_execute_procedure (p_dev_rec)) != BTM_CMD_STARTED)
-            btm_sec_dev_rec_cback_event (p_dev_rec, res, FALSE);
-    }
+    BTM_TRACE_DEBUG ("is_originator:%d ,new_encr_key_256 to %d", p_dev_rec->is_originator,p_dev_rec->new_encryption_key_is_p256);
     return;
 }
 
@@ -4767,7 +4818,7 @@
             "  remote_name:%s", __func__, p_dev_rec->security_required, btm_pair_state_descr(btm_cb.pairing_state),
             reason, bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5], p_dev_rec->sec_bd_name);
 
-    BTM_TRACE_EVENT("%s before update sec_flags=0x%x", __func__, p_dev_rec->sec_flags);
+    BTM_TRACE_EVENT("%s before update sec_flags=0x%x, new_encr_key_256 to %d ", __func__, p_dev_rec->sec_flags,p_dev_rec->new_encryption_key_is_p256);
 
     /* If we are in the process of bonding we need to tell client that auth failed */
     if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
@@ -4837,7 +4888,7 @@
     p_dev_rec->security_required = BTM_SEC_NONE;
 
     p_callback = p_dev_rec->p_callback;
-
+    p_dev_rec->new_encryption_key_is_p256 = FALSE;
     /* if security is pending, send callback to clean up the security state */
     if(p_callback)
     {
@@ -4846,7 +4897,7 @@
         (*p_callback) (p_dev_rec->bd_addr, transport, p_dev_rec->p_ref_data, BTM_ERR_PROCESSING);
     }
 
-    BTM_TRACE_EVENT("%s after update sec_flags=0x%x", __func__, p_dev_rec->sec_flags);
+    BTM_TRACE_EVENT("%s after update sec_flags=0x%x,new_encr_key_256 to %d", __func__, p_dev_rec->sec_flags,p_dev_rec->new_encryption_key_is_p256);
 }
 
 /*******************************************************************************
@@ -5024,6 +5075,7 @@
     l2c_pin_code_request (p_bda);
 
     /* The link key is not in the database and it is not known to the manager */
+    LOG_INFO(LOG_TAG, "%s: btsnd_hcic_link_key_neg_reply: p_dev_rec->sec_flags : %d" , __func__, p_dev_rec->sec_flags);
     btsnd_hcic_link_key_neg_reply (p_bda);
 }
 
@@ -5064,7 +5116,10 @@
 
         case BTM_PAIR_STATE_WAIT_LOCAL_PIN:
             if ( (btm_cb.pairing_flags & BTM_PAIR_FLAGS_PRE_FETCH_PIN) == 0)
+            {
+                LOG_INFO(LOG_TAG, "%s: btsnd_hcic_pin_code_neg_reply: btm_cb.pairing_flags : %d" , __func__, btm_cb.pairing_flags);
                 btsnd_hcic_pin_code_neg_reply (p_cb->pairing_bda);
+            }
             btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
             /* We need to notify the UI that no longer need the PIN */
             if (btm_cb.api.p_auth_complete_callback)
@@ -5090,6 +5145,7 @@
 
 #if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
         case BTM_PAIR_STATE_KEY_ENTRY:
+            LOG_INFO(LOG_TAG, "%s: btsnd_hcic_user_passkey_neg_reply: BTM_LOCAL_IO_CAPS : %d" , __func__, BTM_LOCAL_IO_CAPS);
             btsnd_hcic_user_passkey_neg_reply(p_cb->pairing_bda);
             /* btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE); */
             break;
@@ -5128,6 +5184,23 @@
         case BTM_PAIR_STATE_GET_REM_NAME:
             /* We need to notify the UI that timeout has happened while waiting for authentication*/
             btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
+            tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (p_cb->pairing_bda, BT_TRANSPORT_BR_EDR);
+            /* If no channels on the connection, start idle timeout */
+            if ((p_lcb) && p_lcb->in_use && (p_lcb->link_state == LST_CONNECTED))
+            {
+                if (!p_lcb->ccb_queue.p_first_ccb)
+                {
+                    BTM_TRACE_WARNING("%s start idle timeout if no ccbs", __func__ );
+                    l2cu_no_dynamic_ccbs (p_lcb);
+                }
+                else
+                {
+                    BTM_TRACE_ERROR("%s hci disc triggered when last channel disconnects BDA: %08x%04x",
+                                __func__,
+                                (p_cb->pairing_bda[0]<<24) + (p_cb->pairing_bda[1]<<16) + (p_cb->pairing_bda[2]<<8) + p_cb->pairing_bda[3],
+                                (p_cb->pairing_bda[4] << 8) + p_cb->pairing_bda[5]);
+                }
+            }
             if (btm_cb.api.p_auth_complete_callback)
             {
                 if (p_dev_rec == NULL)
@@ -5175,6 +5248,7 @@
         if ( (memcmp (p_bda, btm_cb.pairing_bda, BD_ADDR_LEN) == 0)  &&
              (btm_cb.pairing_state == BTM_PAIR_STATE_WAIT_AUTH_COMPLETE) )
         {
+             LOG_INFO(LOG_TAG, "%s: btsnd_hcic_pin_code_neg_reply: btm_cb.pairing_state : %d", __func__, btm_cb.pairing_state);
              btsnd_hcic_pin_code_neg_reply (p_bda);
              return;
         }
@@ -5183,6 +5257,7 @@
         {
             BTM_TRACE_WARNING ("btm_sec_pin_code_request() rejected - state: %s",
                                 btm_pair_state_descr(btm_cb.pairing_state));
+            LOG_INFO(LOG_TAG,"%s btsnd_hcic_pin_code_neg_reply", __func__);
             btsnd_hcic_pin_code_neg_reply (p_bda);
             return;
         }
@@ -5274,6 +5349,12 @@
         }
         else
         {
+            if ((p_dev_rec->sec_state == BTM_SEC_STATE_GETTING_NAME) &&
+                 (memcmp (p_dev_rec->bd_addr, p_bda, BD_ADDR_LEN) == 0))
+            {
+                BTM_TRACE_WARNING("RNR initiated by security module and in progress");
+                return;
+            }
             BTM_TRACE_EVENT ("btm_sec_pin_code_request going for remote name");
 
             /* We received PIN code request for the device with unknown name */
@@ -5345,7 +5426,7 @@
 **                  BTM_NO_RESOURCES  - permission declined
 **
 *******************************************************************************/
-static tBTM_STATUS btm_sec_execute_procedure (tBTM_SEC_DEV_REC *p_dev_rec)
+extern tBTM_STATUS btm_sec_execute_procedure (tBTM_SEC_DEV_REC *p_dev_rec)
 {
     BTM_TRACE_EVENT ("btm_sec_execute_procedure: Required:0x%x Flags:0x%x State:%d",
                       p_dev_rec->security_required, p_dev_rec->sec_flags, p_dev_rec->sec_state);
@@ -5455,8 +5536,7 @@
     {
         BTM_TRACE_EVENT ("service id:%d, is trusted:%d",
                           p_dev_rec->p_cur_service->service_id,
-                          (BTM_SEC_IS_SERVICE_TRUSTED(p_dev_rec->trusted_mask,
-                                                      p_dev_rec->p_cur_service->service_id)));
+                          btm_serv_trusted(p_dev_rec,p_dev_rec->p_cur_service));
         if ((btm_sec_are_all_trusted(p_dev_rec->trusted_mask) == FALSE) &&
             (p_dev_rec->p_cur_service->service_id < BTM_SEC_MAX_SERVICES) &&
             (BTM_SEC_IS_SERVICE_TRUSTED(p_dev_rec->trusted_mask,
@@ -5958,6 +6038,7 @@
 {
     tBTM_SEC_CALLBACK   *p_callback = p_dev_rec->p_callback;
 
+    BTM_TRACE_DEBUG ("%s ",__func__);
     if (p_dev_rec->p_callback)
     {
         p_dev_rec->p_callback = NULL;
diff --git a/stack/btu/btu_hcif.c b/stack/btu/btu_hcif.c
index ee72841..5476f53 100644
--- a/stack/btu/btu_hcif.c
+++ b/stack/btu/btu_hcif.c
@@ -36,6 +36,7 @@
 #include "device/include/controller.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
+#include "osi/include/properties.h"
 #include "bt_types.h"
 #include "bt_utils.h"
 #include "btm_api.h"
@@ -125,7 +126,13 @@
 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
 static void btu_ble_proc_enhanced_conn_cmpl (UINT8 *p, UINT16 evt_len);
 #endif
+static void btu_ble_data_rate_update_evt(UINT8 *p, UINT16 evt_len);
 
+#if (defined BLE_EXTENDED_ADV_SUPPORT && BLE_EXTENDED_ADV_SUPPORT == TRUE)
+static void btu_ble_adv_terminated_evt (UINT8* p);
+static void btu_ble_process_ext_adv_pkt (UINT8 *p);
+static void btu_ble_scan_timeout_evt (void);
+#endif
     #endif
 
 /*******************************************************************************
@@ -333,6 +340,23 @@
                case HCI_BLE_DATA_LENGTH_CHANGE_EVT:
                     btu_ble_data_length_change_evt(p, hci_evt_len);
                     break;
+
+               case HCI_BLE_PHY_UPDATE_EVT:
+                    btu_ble_data_rate_update_evt(p, hci_evt_len);
+                    break;
+
+#if (defined BLE_EXTENDED_ADV_SUPPORT && BLE_EXTENDED_ADV_SUPPORT == TRUE)
+               case HCI_BLE_EXT_ADV_TERMINATED_EVT:
+                    btu_ble_adv_terminated_evt(p);
+                    break;
+
+               case HCI_BLE_EXT_ADV_PKT_RPT_EVT:
+                    btu_ble_process_ext_adv_pkt(p);
+                    break;
+               case HCI_BLE_SCAN_TIMEOUT_EVT:
+                    btu_ble_scan_timeout_evt();
+                    break;
+#endif
             }
             break;
 #endif /* BLE_INCLUDED */
@@ -340,6 +364,9 @@
                 btm_vendor_specific_evt (p, hci_evt_len);
             break;
     }
+#if HCI_RAW_CMD_INCLUDED == TRUE
+    btm_hci_event (p, hci_evt_code , hci_evt_len);
+#endif
 }
 
 /*******************************************************************************
@@ -951,6 +978,8 @@
 
         case HCI_BLE_TRANSMITTER_TEST:
         case HCI_BLE_RECEIVER_TEST:
+        case HCI_BLE_ENH_TRANSMITTER_TEST:
+        case HCI_BLE_ENH_RECEIVER_TEST:
         case HCI_BLE_TEST_END:
             btm_ble_test_command_complete(p);
             break;
@@ -975,8 +1004,23 @@
         case HCI_BLE_READ_RESOLVABLE_ADDR_LOCAL:
         case HCI_BLE_SET_ADDR_RESOLUTION_ENABLE:
         case HCI_BLE_SET_RAND_PRIV_ADDR_TIMOUT:
-            break;
+             break;
 #endif
+        /* adv extension complete events*/
+#if (defined BLE_EXTENDED_ADV_SUPPORT && BLE_EXTENDED_ADV_SUPPORT == TRUE)
+        case HCI_BLE_WRITE_EXTENDED_ADV_RPA:
+        case HCI_BLE_WRITE_EXTENDED_ADV_DATA:
+        case HCI_BLE_WRITE_EXTENDED_SCAN_RSP_DATA:
+        case HCI_BLE_WRITE_EXTENDED_ADV_PARAMS:
+        case HCI_BLE_WRITE_EXTENDED_ADV_ENABLE:
+            btm_ble_adv_extension_operation_complete(p, opcode);
+            break;
+        case HCI_BLE_READ_MAX_ADV_LENGTH:
+            btm_ble_read_inst_length_complete (p, evt_len);
+            break;
+
+#endif
+
 #endif /* (BLE_INCLUDED == TRUE) */
 
         default:
@@ -1243,7 +1287,25 @@
 
     /* Reset the controller */
     if (BTM_IsDeviceUp())
-        BTM_DeviceReset (NULL);
+        BTM_HCI_Reset();
+
+    if(*p == 0x0f || (*p == 0x0a))
+    {
+       HCI_TRACE_ERROR("Ctlr H/w error event - code:Tigger SSR");
+       bte_ssr_cleanup(0x33);//SSR reason 0x33 = HW ERR EVT
+       usleep(20000); /* 20 milliseconds */
+       //Reset SOC status to trigger hciattach service
+       if(osi_property_set("bluetooth.status", "off") < 0)
+       {
+          ALOGE("SSR: Error resetting SOC status\n ");
+       }
+       else
+       {
+          ALOGE("SSR: SOC Status is reset\n ");
+       }
+       /* Killing the process to force a restart as part of fault tolerance */
+       kill(getpid(), SIGKILL);
+    }
 }
 
 /*******************************************************************************
@@ -1277,7 +1339,7 @@
     STREAM_TO_UINT8 (status, p);
     STREAM_TO_BDADDR (bda, p);
     STREAM_TO_UINT8  (role, p);
-
+    btm_blacklist_role_change_device(bda, status);
     l2c_link_role_changed (bda, role, status);
     btm_acl_role_changed(status, bda, role);
 }
@@ -1713,13 +1775,33 @@
 {
     HCI_TRACE_EVENT("btu_ble_process_adv_pkt");
 
-    btm_ble_process_adv_pkt(p);
+    btm_ble_process_adv_pkt(p, FALSE);
 }
 
+
+
 static void btu_ble_ll_conn_complete_evt ( UINT8 *p, UINT16 evt_len)
 {
     btm_ble_conn_complete(p, evt_len, FALSE);
 }
+
+#if (defined BLE_EXTENDED_ADV_SUPPORT && BLE_EXTENDED_ADV_SUPPORT == TRUE)
+static void btu_ble_adv_terminated_evt (UINT8 *p)
+{
+    btm_ble_adv_set_terminated_evt(p);
+}
+
+static void btu_ble_process_ext_adv_pkt (UINT8 *p)
+{
+    btm_ble_process_adv_pkt(p, TRUE);
+}
+
+static void btu_ble_scan_timeout_evt (void)
+{
+    btm_ble_scan_timeout_evt();
+}
+#endif
+
 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
 static void btu_ble_proc_enhanced_conn_cmpl( UINT8 *p, UINT16 evt_len)
 {
@@ -1804,5 +1886,25 @@
 }
 #endif /* BLE_LLT_INCLUDED */
 
+static void btu_ble_data_rate_update_evt(UINT8 *p, UINT16 evt_len)
+{
+    UINT8 status;
+    UINT16 handle;
+    UINT8 tx_phy;
+    UINT8 rx_phy;
+
+    if(!controller_get_interface()->supports_ble_two_mbps_rate())
+    {
+        HCI_TRACE_WARNING("%s, request not supported", __func__);
+        return;
+    }
+    STREAM_TO_UINT8(status, p);
+    STREAM_TO_UINT16(handle, p);
+    STREAM_TO_UINT8(tx_phy, p);
+    STREAM_TO_UINT8(rx_phy, p);
+    HCI_TRACE_DEBUG("%s Phy update evt, status=%d, handle = 0x%0x, tx_phy=%d, rx_phy=%d",
+                     __func__, status, handle, tx_phy, rx_phy);
+}
+
 #endif /* BLE_INCLUDED */
 
diff --git a/stack/gap/gap_conn.c b/stack/gap/gap_conn.c
index 1ee2c97..55df7cf 100644
--- a/stack/gap/gap_conn.c
+++ b/stack/gap/gap_conn.c
@@ -137,8 +137,9 @@
     if ((p_ccb = gap_allocate_ccb()) == NULL)
         return (GAP_INVALID_HANDLE);
 
-    /* update the transport */
+    /* update the transport ,service_id */
     p_ccb->transport = transport;
+    p_ccb->service_id = service_id;
 
     /* If caller specified a BD address, save it */
     if (p_rem_bda)
@@ -168,7 +169,7 @@
         p_ccb->cfg = *p_cfg;
 
     /* Configure L2CAP COC, if transport is LE */
-    if (transport == BT_TRANSPORT_LE)
+    if (p_cfg && transport == BT_TRANSPORT_LE)
     {
         p_ccb->local_coc_cfg.credits = L2CAP_LE_DEFAULT_CREDIT;
         p_ccb->local_coc_cfg.mtu = p_cfg->mtu;
@@ -216,7 +217,6 @@
     }
 
     /* Register with Security Manager for the specific security level */
-    p_ccb->service_id = service_id;
     if (!BTM_SetSecurityLevel ((UINT8)!is_server, p_serv_name,
                 p_ccb->service_id, security, p_ccb->psm, 0, 0))
     {
@@ -690,7 +690,7 @@
 
 /*******************************************************************************
 **
-** Function         gap_tx_connect_ind
+** Function         gap_tx_complete_ind
 **
 ** Description      Sends out GAP_EVT_TX_EMPTY when transmission has been
 **                  completed.
@@ -709,6 +709,11 @@
         GAP_TRACE_EVENT("%s: GAP_EVT_TX_EMPTY", __func__);
         p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_TX_EMPTY);
     }
+    else if ((p_ccb->con_state == GAP_CCB_STATE_CONNECTED) && (sdu_sent >= 1))
+    {
+        GAP_TRACE_EVENT("%s: GAP_EVT_TX_DONE", __func__);
+        p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_TX_DONE);
+    }
 }
 
 /*******************************************************************************
@@ -1201,6 +1206,7 @@
     UINT16       xx;
     UINT16      psm = p_ccb->psm;
     UINT8       service_id = p_ccb->service_id;
+    tGAP_CCB    *p_ccb_local = NULL;
 
     /* Drop any buffers we may be holding */
     p_ccb->rx_queue_size = 0;
@@ -1218,10 +1224,13 @@
     p_ccb->con_state = GAP_CCB_STATE_IDLE;
 
     /* If no-one else is using the PSM, deregister from L2CAP */
-    for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
+    for (xx = 0, p_ccb_local = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb_local++)
     {
-        if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->psm == psm))
+        if ((p_ccb_local->con_state != GAP_CCB_STATE_IDLE) && (p_ccb_local->psm == psm))
+        {
+            GAP_TRACE_WARNING(" %s :  %d  PSM is already in use", __func__,p_ccb_local->psm);
             return;
+        }
     }
 
     /* Free the security record for this PSM */
diff --git a/stack/gatt/gatt_api.c b/stack/gatt/gatt_api.c
index 597dc63..e343d18 100644
--- a/stack/gatt/gatt_api.c
+++ b/stack/gatt/gatt_api.c
@@ -34,6 +34,8 @@
 #include "l2c_api.h"
 #include "btm_int.h"
 
+#define SYSTEM_APP_GATT_IF  3
+
 /*******************************************************************************
 **
 ** Function         GATT_SetTraceLevel
@@ -1277,6 +1279,11 @@
             if (gatt_get_ch_state(p_tcb) != GATT_CH_CLOSE)
             {
                 gatt_update_app_use_link_flag(gatt_if, p_tcb,  FALSE, TRUE);
+                if ((gatt_if > SYSTEM_APP_GATT_IF) && (!gatt_num_apps_hold_link(p_tcb)))
+                {
+                    /* this will disconnect the link or cancel the pending connect request at lower layer*/
+                    gatt_disconnect(p_tcb);
+                }
             }
 
             for (j = 0, p_clcb= &gatt_cb.clcb[j]; j < GATT_CL_MAX_LCB; j++, p_clcb++)
diff --git a/stack/gatt/gatt_db.c b/stack/gatt/gatt_db.c
index cffcc70..3be01a1 100644
--- a/stack/gatt/gatt_db.c
+++ b/stack/gatt/gatt_db.c
@@ -62,7 +62,8 @@
 BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service,  BOOLEAN is_pri,
                                UINT16 s_hdl, UINT16 num_handle)
 {
-    p_db->svc_buffer = fixed_queue_new(SIZE_MAX);
+    if(!p_db->svc_buffer)
+       p_db->svc_buffer = fixed_queue_new(SIZE_MAX);
 
     if (!allocate_svc_db_buf(p_db))
     {
@@ -990,14 +991,16 @@
     }
     else if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_32)
     {
-        GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid32 = [0x%08x] perm=0x%02x ",
-                          p_attr32->handle, p_attr32->uuid, p_attr32->permission);
+        if (p_attr32)
+           GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid32 = [0x%08x] perm=0x%02x ",
+                             p_attr32->handle, p_attr32->uuid, p_attr32->permission);
     }
     else
     {
-        GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid128 = [0x%02x:0x%02x] perm=0x%02x ",
-                          p_attr128->handle, p_attr128->uuid[0],p_attr128->uuid[1],
-                          p_attr128->permission);
+        if (p_attr128)
+           GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid128 = [0x%02x:0x%02x] perm=0x%02x ",
+                             p_attr128->handle, p_attr128->uuid[0],p_attr128->uuid[1],
+                             p_attr128->permission);
     }
     return(void *)p_attr16;
 }
diff --git a/stack/gatt/gatt_main.c b/stack/gatt/gatt_main.c
index 4f1568a..72d56a3 100644
--- a/stack/gatt/gatt_main.c
+++ b/stack/gatt/gatt_main.c
@@ -29,6 +29,7 @@
 #include "bt_common.h"
 #include "gatt_int.h"
 #include "l2c_api.h"
+#include "l2c_int.h"
 #include "btm_int.h"
 #include "btm_ble_int.h"
 #include "bt_utils.h"
@@ -240,7 +241,12 @@
         {
             if (p_tcb->att_lcid == L2CAP_ATT_CID)
             {
-                if (ch_state == GATT_CH_OPEN)
+                tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(p_tcb->peer_bda, p_tcb->transport);
+                tL2C_LINK_STATE link_state = p_lcb != NULL ? p_lcb->link_state : LST_DISCONNECTED;
+                GATT_TRACE_WARNING("%s, ch_state=%d, link_state=%d", __func__, ch_state, link_state);
+
+                if ((ch_state == GATT_CH_OPEN) ||
+                        ((ch_state == GATT_CH_CONN) && (link_state == LST_CONNECTED)))
                 {
                     /* only LCB exist between remote device and local */
                     ret = L2CA_RemoveFixedChnl (L2CAP_ATT_CID, p_tcb->peer_bda);
@@ -249,6 +255,8 @@
                 {
                     gatt_set_ch_state(p_tcb, GATT_CH_CLOSING);
                     ret = L2CA_CancelBleConnectReq (p_tcb->peer_bda);
+                    if (!ret)
+                        gatt_set_ch_state(p_tcb, GATT_CH_CLOSE);
                 }
             }
             else
@@ -279,6 +287,13 @@
 *******************************************************************************/
 BOOLEAN gatt_update_app_hold_link_status(tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add)
 {
+    for (int i = 0; i < GATT_MAX_APPS; i++) {
+        if (p_tcb->app_hold_link[i] == gatt_if && is_add) {
+            GATT_TRACE_DEBUG("%s: gatt_if %d already exists at idx %d", __func__, gatt_if, i);
+            return true;
+        }
+    }
+
     for (int i=0; i<GATT_MAX_APPS; i++) {
         if (p_tcb->app_hold_link[i] == 0 && is_add) {
             p_tcb->app_hold_link[i] = gatt_if;
@@ -398,7 +413,7 @@
     if (ret)
     {
         if (!opportunistic)
-            gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, FALSE);
+            gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, TRUE);
         else
             GATT_TRACE_DEBUG("%s: connection is opportunistic, not updating app usage",
                             __func__);
@@ -432,6 +447,8 @@
                        (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
                        (bd_addr[4]<<8)+bd_addr[5], (connected) ? "connected" : "disconnected");
 
+    if (reason == GATT_CONN_TIMEOUT || reason == GATT_CONN_LMP_TIMEOUT)
+        GENERATE_VENDOR_LOGS();
     if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(bd_addr)) != NULL)
     {
         check_srv_chg = TRUE;
diff --git a/stack/gatt/gatt_sr.c b/stack/gatt/gatt_sr.c
index e159bae..3ffac96 100644
--- a/stack/gatt/gatt_sr.c
+++ b/stack/gatt/gatt_sr.c
@@ -330,6 +330,7 @@
     UINT32  trans_id = 0;
     tGATT_IF gatt_if;
     UINT16  conn_id;
+    BT_HDR  *p_buf;
 
 #if GATT_CONFORMANCE_TESTING == TRUE
     if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
@@ -379,7 +380,8 @@
     else /* nothing needs to be executed , send response now */
     {
         GATT_TRACE_ERROR("gatt_process_exec_write_req: no prepare write pending");
-        gatt_send_error_rsp(p_tcb, GATT_ERROR, GATT_REQ_EXEC_WRITE, 0, FALSE);
+        if ((p_buf = attp_build_sr_msg(p_tcb, GATT_RSP_EXEC_WRITE, NULL)) != NULL)
+            attp_send_sr_msg (p_tcb, p_buf);
     }
 }
 
diff --git a/stack/gatt/gatt_utils.c b/stack/gatt/gatt_utils.c
index c2db770..a899110 100644
--- a/stack/gatt/gatt_utils.c
+++ b/stack/gatt/gatt_utils.c
@@ -23,6 +23,7 @@
  ******************************************************************************/
 #include "bt_target.h"
 #include "bt_utils.h"
+#include "stack_config.h"
 
 #if BLE_INCLUDED == TRUE
     #include <string.h>
@@ -1287,6 +1288,7 @@
 
     GATT_TRACE_WARNING("%s disconnecting...", __func__);
     gatt_disconnect (p_clcb->p_tcb);
+    GENERATE_VENDOR_LOGS();
 }
 
 /*******************************************************************************
@@ -2840,12 +2842,18 @@
 
         if (listening != GATT_LISTEN_TO_NONE)
         {
-            connectability |= BTM_BLE_CONNECTABLE;
+           GATT_TRACE_DEBUG ("connectability =%d\n", connectability);
+           connectability |= BTM_BLE_CONNECTABLE;
         }
         else
         {
             if ((connectability & BTM_BLE_CONNECTABLE) == 0)
-            connectability &= ~BTM_BLE_CONNECTABLE;
+            {
+               if (stack_config_get_interface()->get_pts_le_nonconn_adv_enabled())
+                  connectability = BTM_BLE_ADV_STOP;
+               else
+                  connectability &= ~BTM_BLE_CONNECTABLE;
+            }
         }
         /* turning on the adv now */
         btm_ble_set_connectability(connectability);
diff --git a/stack/hcic/hciblecmds.c b/stack/hcic/hciblecmds.c
index 5d58449..08d077e 100644
--- a/stack/hcic/hciblecmds.c
+++ b/stack/hcic/hciblecmds.c
@@ -221,6 +221,72 @@
     return (TRUE);
 }
 
+BOOLEAN btsnd_hcic_ble_set_extended_scan_params (UINT8 scan_phys,
+                                          UINT8 scan_type,
+                                          UINT16 scan_int, UINT16 scan_win,
+                                          UINT16 scan_int_coded, UINT16 scan_win_coded,
+                                          UINT8 addr_type_own, UINT8 scan_filter_policy)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);
+
+    if(scan_phys == 0)
+        scan_phys = HCIC_SCAN_PHY_LE_1M;
+
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_WRITE_EXT_SCAN_PARAMS);
+
+    if((scan_phys == HCIC_SCAN_PHY_LE_1M) || (scan_phys == HCIC_SCAN_PHY_LE_CODED))
+    {
+        p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_EXT_SCAN_PARAM;
+        UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_WRITE_EXT_SCAN_PARAM);
+    }
+    else if(scan_phys == HCIC_SCAN_PHY_LE_1M_CODED)
+    {
+        p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_EXT_SCAN_PARAM + 5;
+        UINT8_TO_STREAM (pp, (HCIC_PARAM_SIZE_BLE_WRITE_EXT_SCAN_PARAM + 5));
+    }
+    UINT8_TO_STREAM (pp, addr_type_own);
+    UINT8_TO_STREAM (pp, scan_filter_policy);
+    UINT8_TO_STREAM (pp, scan_phys);
+    UINT8_TO_STREAM (pp, scan_type);
+    UINT16_TO_STREAM (pp, scan_int);
+    UINT16_TO_STREAM (pp, scan_win);
+
+
+    if(scan_phys == HCIC_SCAN_PHY_LE_1M_CODED)
+    {
+        UINT8_TO_STREAM (pp, scan_type);
+        UINT16_TO_STREAM (pp, scan_int_coded);
+        UINT16_TO_STREAM (pp, scan_win_coded);
+    }
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_set_extended_scan_enable (UINT8 scan_enable, UINT8 duplicate,
+                                                 UINT16 duraton, UINT16 period)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);
+
+    p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_EXT_SCAN_ENABLE;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_WRITE_EXT_SCAN_ENABLE);
+    UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_BLE_WRITE_EXT_SCAN_ENABLE);
+
+    UINT8_TO_STREAM (pp, scan_enable);
+    UINT8_TO_STREAM (pp, duplicate);
+    UINT16_TO_STREAM (pp, duraton);
+    UINT16_TO_STREAM (pp, period);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
 /* link layer connection management commands */
 BOOLEAN btsnd_hcic_ble_create_ll_conn (UINT16 scan_int, UINT16 scan_win,
                                        UINT8 init_filter_policy,
@@ -259,6 +325,63 @@
     return (TRUE);
 }
 
+BOOLEAN btsnd_hcic_ble_ext_create_ll_conn (UINT8 ini_phy, UINT16 scan_int, UINT16 scan_win,
+                                       UINT8 init_filter_policy,
+                                       UINT8 addr_type_peer, BD_ADDR bda_peer,
+                                       UINT8 addr_type_own,
+                                       UINT16 conn_int_min, UINT16 conn_int_max,
+                                       UINT16 conn_latency, UINT16 conn_timeout,
+                                       UINT16 min_ce_len, UINT16 max_ce_len)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);
+
+    p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_EXT_CREATE_LL_CONN;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_EXT_CREATE_LL_CONN);
+    if(ini_phy == HCIC_SCAN_PHY_LE_1M || ini_phy == HCIC_SCAN_PHY_LE_CODED)
+    {
+        p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_EXT_CREATE_LL_CONN;
+        UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_BLE_EXT_CREATE_LL_CONN);
+    }
+    else if(ini_phy == HCIC_SCAN_PHY_LE_1M_CODED)
+    {
+        p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_EXT_CREATE_LL_CONN + 16;
+        UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_BLE_EXT_CREATE_LL_CONN + 16);
+    }
+
+    UINT8_TO_STREAM (pp, init_filter_policy);
+    UINT8_TO_STREAM (pp, addr_type_own);
+    UINT8_TO_STREAM (pp, addr_type_peer);
+    BDADDR_TO_STREAM (pp, bda_peer);
+    UINT8_TO_STREAM (pp, ini_phy);
+
+    UINT16_TO_STREAM (pp, scan_int);
+    UINT16_TO_STREAM (pp, scan_win);
+    UINT16_TO_STREAM (pp, conn_int_min);
+    UINT16_TO_STREAM (pp, conn_int_max);
+    UINT16_TO_STREAM (pp, conn_latency);
+    UINT16_TO_STREAM (pp, conn_timeout);
+    UINT16_TO_STREAM (pp, min_ce_len);
+    UINT16_TO_STREAM (pp, max_ce_len);
+
+    if(ini_phy == HCIC_SCAN_PHY_LE_1M_CODED)
+    {
+        UINT16_TO_STREAM (pp, scan_int);
+        UINT16_TO_STREAM (pp, scan_win);
+        UINT16_TO_STREAM (pp, conn_int_min);
+        UINT16_TO_STREAM (pp, conn_int_max);
+        UINT16_TO_STREAM (pp, conn_latency);
+        UINT16_TO_STREAM (pp, conn_timeout);
+        UINT16_TO_STREAM (pp, min_ce_len);
+        UINT16_TO_STREAM (pp, max_ce_len);
+    }
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
 BOOLEAN btsnd_hcic_ble_create_conn_cancel (void)
 {
     BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
@@ -525,6 +648,25 @@
     return (TRUE);
 }
 
+BOOLEAN btsnd_hcic_ble_enh_receiver_test(UINT8 rx_freq, UINT8 phy, UINT8 mod_index)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);
+
+    p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM3;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_ENH_RECEIVER_TEST);
+    UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_WRITE_PARAM3);
+
+    UINT8_TO_STREAM (pp, rx_freq);
+    UINT8_TO_STREAM (pp, phy);
+    UINT8_TO_STREAM (pp, mod_index);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
 BOOLEAN btsnd_hcic_ble_transmitter_test(UINT8 tx_freq, UINT8 test_data_len, UINT8 payload)
 {
     BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
@@ -544,6 +686,26 @@
     return (TRUE);
 }
 
+BOOLEAN btsnd_hcic_ble_enh_transmitter_test(UINT8 tx_freq, UINT8 test_data_len, UINT8 payload, UINT8 phy)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);
+
+    p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM4;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_ENH_TRANSMITTER_TEST);
+    UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_WRITE_PARAM4);
+
+    UINT8_TO_STREAM (pp, tx_freq);
+    UINT8_TO_STREAM (pp, test_data_len);
+    UINT8_TO_STREAM (pp, payload);
+    UINT8_TO_STREAM (pp, phy);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
 BOOLEAN btsnd_hcic_ble_test_end(void)
 {
     BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
@@ -661,6 +823,26 @@
     return (TRUE);
 }
 
+BOOLEAN btsnd_hcic_ble_set_privacy_mode (UINT8 addr_type_peer, BD_ADDR bda_peer, UINT8 privacy_type)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);
+
+    p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_SET_PRIVACY_MODE;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_SET_PRIVACY_MODE);
+    UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_SET_PRIVACY_MODE);
+    UINT8_TO_STREAM (pp, addr_type_peer);
+    BDADDR_TO_STREAM (pp, bda_peer);
+    UINT8_TO_STREAM (pp, privacy_type);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+    return (TRUE);
+}
+
+
 BOOLEAN btsnd_hcic_ble_clear_resolving_list (void)
 {
     BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
@@ -766,5 +948,217 @@
     return TRUE;
 }
 
-#endif
+BOOLEAN btsnd_hcic_ble_set_default_data_rate(UINT8 all_phy, UINT8 tx_phy, UINT8 rx_phy)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);;
 
+    p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_DEFAULT_PHY;
+    p->offset = 0;
+
+    UINT16_TO_STREAM(pp, HCI_BLE_SET_DEFAULT_PHY_RATE);
+    UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_BLE_WRITE_DEFAULT_PHY);
+
+    UINT8_TO_STREAM(pp, all_phy);
+    UINT8_TO_STREAM(pp, tx_phy);
+    UINT8_TO_STREAM(pp, rx_phy);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+    return TRUE;
+}
+
+BOOLEAN btsnd_hcic_ble_set_data_rate(UINT16 handle, UINT8 all_phy, UINT8 tx_phy,
+                                     UINT8 rx_phy, UINT16 phy_options)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);;
+
+    p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_PHY;
+    p->offset = 0;
+
+    UINT16_TO_STREAM(pp, HCI_BLE_SET_PHY_RATE);
+    UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_BLE_WRITE_PHY);
+
+    UINT16_TO_STREAM(pp, handle);
+    UINT8_TO_STREAM(pp, all_phy);
+    UINT8_TO_STREAM(pp, tx_phy);
+    UINT8_TO_STREAM(pp, rx_phy);
+    UINT16_TO_STREAM(pp, phy_options);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+    return TRUE;
+}
+
+BOOLEAN btsnd_hcic_ble_set_extended_adv_params (UINT8 set_id, UINT16 event_properties,
+                                              UINT32 adv_int_min, UINT32 adv_int_max,
+                                              UINT8 channel_map, UINT8 addr_type_own,
+                                              UINT8 addr_type_dir, BD_ADDR direct_bda,
+                                              UINT8 adv_filter_policy, UINT8 adv_tx_power,
+                                              UINT8 primary_adv_phy, UINT8 secondary_max_skip,
+                                              UINT8 secondary_adv_phy, UINT8 advertising_sid,
+                                              UINT8 scan_req_not_enb)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);;
+
+    p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_EXTENDED_ADV_PARAMS ;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_WRITE_EXTENDED_ADV_PARAMS);
+    UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_BLE_WRITE_EXTENDED_ADV_PARAMS);
+    UINT8_TO_STREAM (pp, set_id);
+    UINT16_TO_STREAM (pp, event_properties);
+    UINT24_TO_STREAM (pp, adv_int_min);
+    UINT24_TO_STREAM (pp, adv_int_max);
+    UINT8_TO_STREAM (pp, channel_map);
+    UINT8_TO_STREAM (pp, addr_type_own);
+    UINT8_TO_STREAM (pp, addr_type_dir);
+    BDADDR_TO_STREAM (pp, direct_bda);
+    UINT8_TO_STREAM (pp, adv_filter_policy);
+    UINT8_TO_STREAM (pp, adv_tx_power);
+    UINT8_TO_STREAM (pp, primary_adv_phy);
+    UINT8_TO_STREAM (pp, secondary_max_skip);
+    UINT8_TO_STREAM (pp, secondary_adv_phy);
+    UINT8_TO_STREAM (pp, advertising_sid);
+    UINT8_TO_STREAM (pp, scan_req_not_enb);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_set_extended_adv_data (UINT8 set_id, UINT8 operation, UINT8 fragment_pref,
+                                              UINT8 data_len, UINT8 *p_data)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);;
+
+    p->len    = HCIC_PREAMBLE_SIZE + data_len + 4;
+    p->offset = 0;
+
+    if (data_len > HCIC_PARAM_SIZE_BLE_WRITE_EXTENDED_ADV_DATA)
+        data_len = HCIC_PARAM_SIZE_BLE_WRITE_EXTENDED_ADV_DATA;
+
+
+    UINT16_TO_STREAM (pp, HCI_BLE_WRITE_EXTENDED_ADV_DATA);
+    UINT8_TO_STREAM  (pp, data_len + 4);
+    UINT8_TO_STREAM  (pp, set_id);
+    UINT8_TO_STREAM  (pp, operation);
+    UINT8_TO_STREAM  (pp, fragment_pref);
+
+    memset(pp, 0, data_len + 1);
+
+    if (p_data != NULL && data_len > 0)
+    {
+        UINT8_TO_STREAM (pp, data_len);
+        ARRAY_TO_STREAM (pp, p_data, data_len);
+    }
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_set_extended_scan_rsp_data (UINT8 set_id, UINT8 operation, UINT8 fragment_pref,
+                                                   UINT8 data_len, UINT8 *p_scan_rsp)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);;
+
+    p->len    = HCIC_PREAMBLE_SIZE + data_len + 4;
+    p->offset = 0;
+
+    if (data_len > HCIC_PARAM_SIZE_BLE_WRITE_EXTENDED_SCAN_RSP )
+            data_len = HCIC_PARAM_SIZE_BLE_WRITE_EXTENDED_SCAN_RSP;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_WRITE_EXTENDED_SCAN_RSP_DATA);
+    UINT8_TO_STREAM  (pp, data_len + 4);
+    UINT8_TO_STREAM  (pp, set_id);
+    UINT8_TO_STREAM  (pp, operation);
+    UINT8_TO_STREAM  (pp, fragment_pref);
+
+    memset(pp, 0, data_len + 1);
+
+    if (p_scan_rsp != NULL && data_len > 0)
+    {
+        UINT8_TO_STREAM (pp, data_len);
+        ARRAY_TO_STREAM (pp, p_scan_rsp, data_len);
+    }
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_set_extended_adv_enable (UINT8 adv_enable, UINT8 num_sets, UINT8* handles,
+                                            UINT16* durations, UINT8* max_adv_events)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);;
+
+    p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_EXTENDED_ADV_ENABLE + num_sets*4;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_WRITE_EXTENDED_ADV_ENABLE);
+    UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_WRITE_EXTENDED_ADV_ENABLE + 4*num_sets);
+
+    UINT8_TO_STREAM (pp, adv_enable);
+    UINT8_TO_STREAM (pp, num_sets);
+
+    if (num_sets > 0) {
+        for (UINT8 count = 0; count < num_sets; count++) {
+            UINT8_TO_STREAM(pp, handles[count]);
+            UINT16_TO_STREAM (pp, durations[count]);
+            UINT8_TO_STREAM(pp, max_adv_events[count]);
+        }
+    }
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_read_num_adv_sets (void)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);;
+
+    p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_READ_CMD;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_READ_NUM_ADV_SETS);
+    UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_READ_CMD);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_write_extended_rpa (UINT8 set_id, BD_ADDR rpa)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);;
+
+    p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_EXTENDED_ADV_RPA;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_WRITE_EXTENDED_ADV_RPA);
+    UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_WRITE_EXTENDED_ADV_RPA);
+    UINT8_TO_STREAM  (pp, set_id);
+    BDADDR_TO_STREAM (pp, rpa);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_read_extended_max_adv_len (void)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);;
+
+    p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_READ_CMD;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_READ_MAX_ADV_LENGTH);
+    UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_READ_CMD);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
+#endif
diff --git a/stack/hcic/hcicmds.c b/stack/hcic/hcicmds.c
index 97e83b7..ba1f6d4 100644
--- a/stack/hcic/hcicmds.c
+++ b/stack/hcic/hcicmds.c
@@ -726,6 +726,21 @@
     return (TRUE);
 }
 
+BOOLEAN btsnd_hcic_reset (UINT8 local_controller_id)
+{
+    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+    UINT8 *pp = (UINT8 *)(p + 1);
+
+    p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_RESET;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_RESET);
+    UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_RESET);
+
+    btu_hcif_send_cmd (local_controller_id,  p);
+    return (TRUE);
+}
+
 BOOLEAN btsnd_hcic_set_event_filter (UINT8 filt_type, UINT8 filt_cond_type,
                                      UINT8 *filt_cond, UINT8 filt_cond_len)
 {
@@ -1443,6 +1458,26 @@
 #error "HCI_CMD_BUF_SIZE must be larger than 268"
 #endif
 
+
+void btsnd_hcic_raw_cmd (void *buffer, UINT16 opcode, UINT8 len,
+                                 UINT8 *p_data, void *p_cmd_cplt_cback)
+{
+    BT_HDR *p = (BT_HDR *)buffer;
+    UINT8 *pp = (UINT8 *)(p + 1);
+
+    p->len    = HCIC_PREAMBLE_SIZE + len;
+    p->offset = sizeof(void *);
+
+    *((void **)pp) = p_cmd_cplt_cback;  /* Store command complete callback in buffer */
+    pp += sizeof(void *);               /* Skip over callback pointer */
+
+    UINT16_TO_STREAM (pp, opcode);
+    UINT8_TO_STREAM  (pp, len);
+    ARRAY_TO_STREAM  (pp, p_data, len);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+}
+
 void btsnd_hcic_vendor_spec_cmd (void *buffer, UINT16 opcode, UINT8 len,
                                  UINT8 *p_data, void *p_cmd_cplt_cback)
 {
diff --git a/stack/hid/hidh_api.c b/stack/hid/hidh_api.c
index db173f1..eb4bf05 100644
--- a/stack/hid/hidh_api.c
+++ b/stack/hid/hidh_api.c
@@ -81,16 +81,20 @@
 
     if ((p_attr = SDP_FindAttributeInRec(p_rec, attr_id)) != NULL)
     {
-        if((name_len = SDP_DISC_ATTR_LEN(p_attr->attr_len_type)) < max_len )
+        if((name_len = SDP_DISC_ATTR_LEN(p_attr->attr_len_type)) < max_len && name_len < 3)
         {
             memcpy( str, (char *) p_attr->attr_value.v.array, name_len );
             str[name_len] = '\0';
         }
-        else
+        else if (max_len < 4)
         {
             memcpy( str, (char *) p_attr->attr_value.v.array, max_len-1 );
             str[max_len-1] = '\0';
         }
+        else
+        {
+            str[0] = '\0';
+        }
     }
     else
         str[0] = '\0';
diff --git a/stack/hid/hidh_conn.c b/stack/hid/hidh_conn.c
index 39ba8bc..a719a0e 100644
--- a/stack/hid/hidh_conn.c
+++ b/stack/hid/hidh_conn.c
@@ -46,6 +46,7 @@
 
 #include "osi/include/osi.h"
 
+#include "device/include/interop.h"
 
 extern fixed_queue_t *btu_general_alarm_queue;
 
@@ -227,6 +228,15 @@
     p_hcon = &hh_cb.devices[i].conn;
     p_dev  = &hh_cb.devices[i];
 
+    /* Stop the retry timer if active */
+#if (HID_HOST_MAX_CONN_RETRY > 0)
+#if (HID_HOST_REPAGE_WIN > 0)
+    HIDH_TRACE_DEBUG ("HID-Host stopping retry timer as l2cap is connected from remote side");
+    p_dev->conn_tries = HID_HOST_MAX_CONN_RETRY+1;
+    alarm_cancel(p_dev->conn.process_repage_timer);
+#endif
+#endif
+
     /* Check we are in the correct state for this */
     if (psm == HID_PSM_INTERRUPT)
     {
@@ -265,18 +275,31 @@
 
     if (psm == HID_PSM_CONTROL)
     {
+        bt_bdaddr_t remote_bdaddr;
         p_hcon->conn_flags = 0;
         p_hcon->ctrl_cid   = l2cap_cid;
         p_hcon->ctrl_id    = l2cap_id;
         p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;  /* In case disconnection occurs before security is completed, then set CLOSE_EVT reason code to 'connection failure' */
 
         p_hcon->conn_state = HID_CONN_STATE_SECURITY;
-        if(btm_sec_mx_access_request (p_dev->addr, HID_PSM_CONTROL,
-            FALSE, BTM_SEC_PROTO_HID,
-            (p_dev->attr_mask & HID_SEC_REQUIRED) ? HID_SEC_CHN : HID_NOSEC_CHN,
-            &hidh_sec_check_complete_term, p_dev) == BTM_CMD_STARTED)
+        bdcpy(remote_bdaddr.address, p_dev->addr);
+
+        if (!interop_match_addr(INTEROP_DISABLE_AUTH_FOR_HID_POINTING, (bt_bdaddr_t *)&remote_bdaddr))
         {
+            if(btm_sec_mx_access_request (p_dev->addr, HID_PSM_CONTROL,
+                FALSE, BTM_SEC_PROTO_HID,
+                (p_dev->attr_mask & HID_SEC_REQUIRED) ? HID_SEC_CHN : HID_NOSEC_CHN,
+                &hidh_sec_check_complete_term, p_dev) == BTM_CMD_STARTED)
+            {
+                L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK);
+            }
+        }
+        else
+        {
+            /* device is blacklisted, don't perform authentication */
             L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK);
+            hidh_sec_check_complete_term(p_dev->addr, BT_TRANSPORT_BR_EDR,
+                p_dev, BTM_SUCCESS);
         }
 
         return;
@@ -299,6 +322,7 @@
 void hidh_process_repage_timer_timeout(void *data)
 {
   uint8_t dhandle = PTR_TO_UINT(data);
+  GENERATE_VENDOR_LOGS();
   hidh_try_repage(dhandle);
 }
 
@@ -313,15 +337,17 @@
 *******************************************************************************/
 void hidh_try_repage(UINT8 dhandle)
 {
-    tHID_HOST_DEV_CTB *device;
+    HIDH_TRACE_DEBUG ("HID-Host Connection retry timeout fired");
+    if (HID_SUCCESS == hidh_conn_initiate(dhandle))
+    {
 
-    hidh_conn_initiate(dhandle);
+        tHID_HOST_DEV_CTB *device;
+        device = &hh_cb.devices[dhandle];
+        device->conn_tries++;
 
-    device = &hh_cb.devices[dhandle];
-    device->conn_tries++;
-
-    hh_cb.callback(dhandle, device->addr, HID_HDEV_EVT_RETRYING,
-                   device->conn_tries, NULL ) ;
+        hh_cb.callback(dhandle, device->addr, HID_HDEV_EVT_RETRYING,
+                       device->conn_tries, NULL ) ;
+    }
 }
 
 /*******************************************************************************
@@ -368,6 +394,7 @@
             }
         }
 #endif
+        GENERATE_VENDOR_LOGS();
         p_dev->conn.disc_reason = HID_ERR_AUTH_FAILED;      /* Save reason for disconnecting */
         hidh_conn_disconnect(dhandle);
     }
@@ -429,21 +456,35 @@
 #endif
         {
             reason = HID_L2CAP_CONN_FAIL | (UINT32) result ;
+            HIDH_TRACE_WARNING ("HID-Host: l2cap connect failed, reason = %d", reason);
             hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, reason, NULL ) ;
+            GENERATE_VENDOR_LOGS();
         }
         return;
     }
     /* receive Control Channel connect confirmation */
     if (l2cap_cid == p_hcon->ctrl_cid)
     {
+        bt_bdaddr_t remote_address;
+
         /* check security requirement */
         p_hcon->conn_state = HID_CONN_STATE_SECURITY;
         p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;  /* In case disconnection occurs before security is completed, then set CLOSE_EVT reason code to "connection failure" */
+        bdcpy(remote_address.address, p_dev->addr);
 
-        btm_sec_mx_access_request (p_dev->addr, HID_PSM_CONTROL,
-            TRUE, BTM_SEC_PROTO_HID,
-            (p_dev->attr_mask & HID_SEC_REQUIRED) ? HID_SEC_CHN : HID_NOSEC_CHN,
-            &hidh_sec_check_complete_orig, p_dev);
+        if (!interop_match_addr(INTEROP_DISABLE_AUTH_FOR_HID_POINTING, (bt_bdaddr_t *)&remote_address))
+        {
+            btm_sec_mx_access_request (p_dev->addr, HID_PSM_CONTROL,
+                TRUE, BTM_SEC_PROTO_HID,
+                (p_dev->attr_mask & HID_SEC_REQUIRED) ? HID_SEC_CHN : HID_NOSEC_CHN,
+                &hidh_sec_check_complete_orig, p_dev);
+        }
+        else
+        {
+            /* device is blacklisted, don't perform authentication */
+             hidh_sec_check_complete_orig(p_dev->addr, BT_TRANSPORT_BR_EDR,
+                p_dev, BTM_SUCCESS);
+        }
     }
     else
     {
@@ -513,7 +554,9 @@
                 reason = HID_L2CAP_REQ_FAIL ;
                 p_hcon->conn_state = HID_CONN_STATE_UNUSED;
                 hidh_conn_disconnect (dhandle);
+                HIDH_TRACE_WARNING ("HID-Host: l2cap config failed, reason = %d", reason);
                 hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, reason, NULL ) ;
+                GENERATE_VENDOR_LOGS();
                 return;
             }
             else
@@ -573,7 +616,9 @@
     {
         hidh_conn_disconnect (dhandle);
         reason = HID_L2CAP_CFG_FAIL | (UINT32) p_cfg->result ;
+        HIDH_TRACE_WARNING ("HID-Host: l2cap config ind failed, reason = %d", reason);
         hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, reason, NULL ) ;
+        GENERATE_VENDOR_LOGS();
         return;
     }
 
@@ -591,7 +636,9 @@
                 reason = HID_L2CAP_REQ_FAIL ;
                 p_hcon->conn_state = HID_CONN_STATE_UNUSED;
                 hidh_conn_disconnect (dhandle);
+                HIDH_TRACE_WARNING ("HID-Host: l2cap config ind failed 2, reason = %d", reason);
                 hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, reason, NULL ) ;
+                GENERATE_VENDOR_LOGS();
                 return;
             }
             else
@@ -665,6 +712,8 @@
         if( !ack_needed )
             disc_res = btm_get_acl_disc_reason_code();
 
+        HIDH_TRACE_EVENT ("HID-Host: acl disconnect reason %d", disc_res);
+
 #if (HID_HOST_MAX_CONN_RETRY > 0)
         if( (disc_res == HCI_ERR_CONNECTION_TOUT || disc_res == HCI_ERR_UNSPECIFIED) &&
             (!(hh_cb.devices[dhandle].attr_mask & HID_RECONN_INIT)) &&
@@ -672,10 +721,12 @@
         {
             hh_cb.devices[dhandle].conn_tries = 0;
             period_ms_t interval_ms = HID_HOST_REPAGE_WIN * 1000;
+            HIDH_TRACE_EVENT ("HID-Host: starting timer for reconnection");
             alarm_set_on_queue(hh_cb.devices[dhandle].conn.process_repage_timer,
                                interval_ms, hidh_process_repage_timer_timeout,
                                UINT_TO_PTR(dhandle), btu_general_alarm_queue);
             hh_cb.callback( dhandle,  hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, disc_res, NULL);
+            GENERATE_VENDOR_LOGS();
         }
         else
 #endif
@@ -695,7 +746,7 @@
             {
                 hid_close_evt_reason = HID_ERR_AUTH_FAILED;
             }
-
+            HIDH_TRACE_EVENT ("HID-Host: disconnect ind, reason = %d", hid_close_evt_reason);
             hh_cb.callback( dhandle,  hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, hid_close_evt_reason, NULL ) ;
         }
     }
@@ -745,6 +796,7 @@
     {
         hh_cb.devices[dhandle].state = HID_DEV_NO_CONN;
         p_hcon->conn_state = HID_CONN_STATE_UNUSED;
+        HIDH_TRACE_EVENT ("HID-Host: disconnect cfm, reason = %d", p_hcon->disc_reason);
         hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, p_hcon->disc_reason, NULL ) ;
     }
 }
@@ -1032,7 +1084,10 @@
     tHID_HOST_DEV_CTB *p_dev = &hh_cb.devices[dhandle];
 
     if( p_dev->conn.conn_state != HID_CONN_STATE_UNUSED )
+    {
+        HIDH_TRACE_WARNING ("HID-Host connection state not unused (%d)", p_dev->conn.conn_state);
         return( HID_ERR_CONN_IN_PROCESS );
+    }
 
     p_dev->conn.ctrl_cid = 0;
     p_dev->conn.intr_cid = 0;
@@ -1054,6 +1109,8 @@
         HIDH_TRACE_WARNING ("HID-Host Originate failed");
         hh_cb.callback( dhandle,  hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE,
                                 HID_ERR_L2CAP_FAILED, NULL ) ;
+        GENERATE_VENDOR_LOGS();
+        return HID_ERR_L2CAP_FAILED;
     }
     else
     {
@@ -1110,10 +1167,12 @@
     p_dev->conn.conn_state = HID_CONN_STATE_UNUSED;
 #if (HID_HOST_REPAGE_WIN > 0)
     period_ms_t interval_ms = HID_HOST_REPAGE_WIN * 1000;
+    HIDH_TRACE_DEBUG ("HID-Host starting timer of %d sec", interval_ms);
     alarm_set_on_queue(p_dev->conn.process_repage_timer,
                        interval_ms, hidh_process_repage_timer_timeout,
                        UINT_TO_PTR(dhandle), btu_general_alarm_queue);
 #else
-    hidh_process_repage_process(dhandle);
+    HIDH_TRACE_DEBUG ("HID-Host calling timeout function");
+    hidh_try_repage(dhandle);
 #endif
 }
diff --git a/stack/include/a2d_aac.h b/stack/include/a2d_aac.h
new file mode 100644
index 0000000..413d486
--- /dev/null
+++ b/stack/include/a2d_aac.h
@@ -0,0 +1,150 @@
+/******************************************************************************
+ *
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *   met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of The Linux Foundation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+  ******************************************************************************/
+
+#ifndef A2D_AAC_H
+#define A2D_AAC_H
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+#define A2D_AAC_MPL_HDR_LEN         1
+
+/* AAC media codec capabilitiy len*/
+#define A2D_AAC_INFO_LEN            8
+
+/* AAC Codec Specific */
+#define A2D_AAC_IE_OBJ_TYPE_MSK                0xF0    /* b7-b4 Object Type */
+#define A2D_AAC_IE_OBJ_TYPE_MPEG_2_AAC_LC      0x80    /* b7:MPEG-2 AAC LC */
+#define A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_LC      0x40    /* b7:MPEG-4 AAC LC */
+#define A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_LTP     0x20    /* b7:MPEG-4 AAC LTP */
+#define A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_SCA     0x10    /* b7:MPEG-4 AAC SCALABLE */
+
+#define A2D_AAC_IE_SAMP_FREQ_MSK               0xFFF0    /* b15-b4 sampling frequency */
+#define A2D_AAC_IE_SAMP_FREQ_8000              0x8000    /* b15: 8000 */
+#define A2D_AAC_IE_SAMP_FREQ_11025             0x4000    /* b15: 11025 */
+#define A2D_AAC_IE_SAMP_FREQ_12000             0x2000    /* b15: 12000 */
+#define A2D_AAC_IE_SAMP_FREQ_16000             0x1000    /* b15: 16000 */
+#define A2D_AAC_IE_SAMP_FREQ_22050             0x0800    /* b15: 22050 */
+#define A2D_AAC_IE_SAMP_FREQ_24000             0x0400    /* b15: 24000 */
+#define A2D_AAC_IE_SAMP_FREQ_32000             0x0200    /* b15: 32000 */
+#define A2D_AAC_IE_SAMP_FREQ_44100             0x0100    /* b15: 441000 */
+#define A2D_AAC_IE_SAMP_FREQ_48000             0x0080    /* b15: 48000 */
+#define A2D_AAC_IE_SAMP_FREQ_64000             0x0040    /* b15: 64000 */
+#define A2D_AAC_IE_SAMP_FREQ_88200             0x0020    /* b15: 88200 */
+#define A2D_AAC_IE_SAMP_FREQ_96000             0x0010    /* b15: 96000 */
+
+
+#define A2D_AAC_IE_CHANNELS_MSK                0x0C    /* b7-b6 channels supported */
+#define A2D_AAC_IE_CHANNELS_1                  0x08    /* Channel 1 */
+#define A2D_AAC_IE_CHANNELS_2                  0x04    /* Channel 2 */
+
+#define A2D_AAC_IE_VBR_MSK                     0x80    /* b7 variable bit rate */
+#define A2D_AAC_IE_VBR_SUPP                    0x80    /* supported */
+#define A2D_AAC_IE_VBR_NOT_SUPP                0x00    /* supported */
+
+#define A2D_AAC_IE_BIT_RATE_MSK                0x007FFFFF  /* bit rate */
+#define A2D_AAC_IE_BIT_RATE                    0x007FFFFF
+
+
+#define BTIF_AAC_DEFAULT_BIT_RATE 0x00028488 //165kbps
+#define BTIF_AAC_MIN_BITRATE 0x0000FA00
+
+typedef struct  {
+    INT16 s16SamplingFreq;  /* 16k, 32k, 44.1k or 48k*/
+    INT16 s16ChannelMode;   /* mono, dual, streo or joint streo*/
+    UINT16 u16BitRate;
+    UINT16 *ps16NextPcmBuffer;
+    UINT8  *pu8Packet;
+    UINT8  *pu8NextPacket;
+    UINT16 u16PacketLength;
+    void* encoder;
+} A2D_AAC_ENC_PARAMS;
+
+/*****************************************************************************
+**  Type Definitions
+*****************************************************************************/
+
+/* AAC Codec Information data type */
+typedef struct
+{
+    UINT8   object_type;    /* Object Type */
+    UINT16  samp_freq;      /* Sampling Frequency */
+    UINT8   channels;       /* Channels */
+    UINT32  bit_rate;       /* bit_rate */
+    UINT8   vbr;            /* variable bit rate */
+} tA2D_AAC_CIE;
+
+
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/******************************************************************************
+**
+** Function         A2D_BldAacInfo
+**
+** Description      This function builds byte sequence for
+**                  Aac Codec Capabilities.
+** Input :           media_type:  Audio or MultiMedia.
+**                  p_ie: AAC Codec Information Element
+**
+** Output :          p_result: codec info.
+**
+** Returns          A2D_SUCCESS if successful.
+**                  Error otherwise.
+******************************************************************************/
+extern tA2D_STATUS A2D_BldAacInfo(UINT8 media_type, tA2D_AAC_CIE *p_ie, UINT8 *p_result);
+
+/******************************************************************************
+**
+** Function         A2D_ParsAacInfo
+**
+** Description      This function parse byte sequence for
+**                  Aac Codec Capabilities.
+** Input :          p_info:  input byte sequence.
+**                  for_caps: True for getcap, false otherwise
+**
+** Output :          p_ie: Aac codec information.
+**
+** Returns          A2D_SUCCESS if successful.
+**                  Error otherwise.
+******************************************************************************/
+extern tA2D_STATUS A2D_ParsAacInfo(tA2D_AAC_CIE *p_ie, UINT8 *p_info, BOOLEAN for_caps);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* A2D_AAC_H */
diff --git a/stack/include/a2d_api.h b/stack/include/a2d_api.h
index 75d2755..fb98368 100644
--- a/stack/include/a2d_api.h
+++ b/stack/include/a2d_api.h
@@ -85,6 +85,9 @@
 #define A2D_BAD_CP_TYPE       0xE0  /* The requested CP Type is not supported. */
 #define A2D_BAD_CP_FORMAT     0xE1  /* The format of Content Protection Service Capability/Content Protection Scheme Dependent Data is not correct. */
 
+
+#define A2D_NON_A2DP_MEDIA_CT 0xFF  /* NON A2DP media codec */
+
 typedef UINT8 tA2D_STATUS;
 
 /* the return values from A2D_BitsSet() */
@@ -203,6 +206,9 @@
 extern tA2D_STATUS A2D_FindService(UINT16 service_uuid, BD_ADDR bd_addr,
                                    tA2D_SDP_DB_PARAMS *p_db, tA2D_FIND_CBACK *p_cback);
 
+/* Used to check local version of AVDTP */
+extern int a2d_get_avdt_sdp_ver ();
+
 /******************************************************************************
 **
 ** Function         A2D_SetTraceLevel
diff --git a/stack/include/a2d_aptx.h b/stack/include/a2d_aptx.h
new file mode 100644
index 0000000..2fb9613
--- /dev/null
+++ b/stack/include/a2d_aptx.h
@@ -0,0 +1,138 @@
+/******************************************************************************
+
+    Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are
+    met:
+        * Redistributions of source code must retain the above copyright
+          notice, this list of conditions and the following disclaimer.
+        * Redistributions in binary form must reproduce the above
+          copyright notice, this list of conditions and the following
+          disclaimer in the documentation and/or other materials provided
+          with the distribution.
+        * Neither the name of The Linux Foundation nor the names of its
+          contributors may be used to endorse or promote products derived
+          from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+    BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+    IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  interface to aptX codec
+ *
+ ******************************************************************************/
+#ifndef A2D_APTX_H
+#define A2D_APTX_H
+
+/* aptX codec specific settings*/
+#define A2D_APTX_CODEC_LEN        9
+
+#define A2D_APTX_VENDOR_ID             (0x0000004F)
+#define A2D_APTX_CODEC_ID_BLUETOOTH    (0x0001)
+#define A2D_APTX_SAMPLERATE_44100       (0x20)
+#define A2D_APTX_SAMPLERATE_48000       (0x10)
+#define A2D_APTX_CHANNELS_STEREO        (0x02)
+#define A2D_APTX_CHANNELS_MONO          (0x01)
+#define A2D_APTX_FUTURE_1        (0x00)
+#define A2D_APTX_FUTURE_2        (0x00)
+#define A2D_APTX_OTHER_FEATURES_NONE  (0x00000000)
+#define A2D_AV_APTX_AUDIO        (0x00)
+#define A2D_APTX_CHANNEL         (0x0001)
+#define A2D_APTX_SAMPLERATE      (0x22)
+
+
+/*****************************************************************************
+**  Type Definitions
+*****************************************************************************/
+typedef enum {
+    APTX_CODEC_NONE=0,
+    APTX_CODEC,
+    APTX_HD_CODEC,
+} A2D_AptXCodecType;
+
+typedef void (*A2D_AptXThreadFn)(void *context);
+typedef UINT32 (*A2D_AptXReadFn) (UINT8 ch_id, UINT16 *p_msg_evt, UINT8* p_buf,
+                                   UINT32 len);
+typedef int (*A2D_AptXBufferSendFn) (UINT8*, int, int);
+typedef void (*A2D_AptXSetPriorityFn)(tHIGH_PRIORITY_TASK task);
+
+typedef struct
+{
+    UINT32 vendorId;
+    UINT16 codecId;         /* Codec ID for aptX */
+    UINT8  sampleRate;     /* Sampling Frequency */
+    UINT8  channelMode;    /* STEREO/DUAL/MONO */
+    UINT8  future1;
+    UINT8  future2;
+} tA2D_APTX_CIE;
+
+typedef struct  {
+    INT16 s16SamplingFreq;  /* 16k, 32k, 44.1k or 48k*/
+    INT16 s16ChannelMode;   /* mono, dual, streo or joint streo*/
+    UINT16 u16BitRate;
+    UINT16 *ps16NextPcmBuffer;
+    UINT8  *pu8Packet;
+    UINT8  *pu8NextPacket;
+    UINT16 u16PacketLength;
+    void* encoder;
+} A2D_APTX_ENC_PARAMS;
+
+extern const char* A2D_APTX_SCHED_LIB_NAME;
+extern void *A2dAptXSchedLibHandle;
+extern BOOLEAN isA2dAptXEnabled;
+extern thread_t *A2d_aptx_thread;
+extern A2D_AptXThreadFn A2d_aptx_thread_fn;
+
+/*****************************************************************************
+**  external function declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+extern UINT8 A2D_BldAptxInfo(UINT8 media_type, tA2D_APTX_CIE *p_ie,
+                             UINT8 *p_result);
+extern UINT8 A2D_ParsAptxInfo(tA2D_APTX_CIE *p_ie, UINT8 *p_info,
+                              BOOLEAN for_caps);
+extern int (*A2D_aptx_encoder_init)(void);
+extern A2D_AptXThreadFn (*A2D_aptx_sched_start)(void *encoder,
+                          A2D_AptXCodecType aptX_codec_type,
+                          BOOLEAN use_SCMS_T, BOOLEAN is_24bit_audio,
+                          UINT16 sample_rate, UINT8 format_bits,
+                          UINT8 channel, UINT16 mtu, A2D_AptXReadFn read_fn,
+                          A2D_AptXBufferSendFn send_fn,
+                          A2D_AptXSetPriorityFn set_priority_fn,
+                          BOOLEAN test, BOOLEAN trace);
+extern BOOLEAN (*A2D_aptx_sched_stop)(void);
+extern void (*A2D_aptx_encoder_deinit)(void);
+extern UINT8 a2d_av_aptx_cfg_in_cap(UINT8 *p_cfg, tA2D_APTX_CIE *p_cap);
+extern BOOLEAN A2D_check_and_init_aptX();
+extern void A2D_start_aptX(void *encoder, A2D_AptXCodecType aptX_codec_type,
+                        BOOLEAN use_SCMS_T, BOOLEAN is_24bit_audio,
+                        UINT16 sample_rate, UINT8 format_bits,
+                        UINT8 channel, UINT16 MTU, A2D_AptXReadFn read_fn,
+                        A2D_AptXBufferSendFn send_fn,
+                        A2D_AptXSetPriorityFn set_priority_fn,
+                        BOOLEAN test, BOOLEAN trace);
+extern void A2D_deinit_aptX();
+extern void A2D_stop_aptX (void);
+extern void A2D_close_aptX();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* A2D_APTX_H */
diff --git a/stack/include/a2d_aptx_hd.h b/stack/include/a2d_aptx_hd.h
new file mode 100644
index 0000000..eca6f26
--- /dev/null
+++ b/stack/include/a2d_aptx_hd.h
@@ -0,0 +1,105 @@
+/******************************************************************************
+
+    Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are
+    met:
+        * Redistributions of source code must retain the above copyright
+          notice, this list of conditions and the following disclaimer.
+        * Redistributions in binary form must reproduce the above
+          copyright notice, this list of conditions and the following
+          disclaimer in the documentation and/or other materials provided
+          with the distribution.
+        * Neither the name of The Linux Foundation nor the names of its
+          contributors may be used to endorse or promote products derived
+          from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+    BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+    IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ******************************************************************************/
+/******************************************************************************
+   interface to aptX HD codec
+ ******************************************************************************/
+#ifndef A2D_APTX_HD_H
+#define A2D_APTX_HD_H
+
+/* aptX HD codec specific settings*/
+#define A2D_APTX_HD_CODEC_LEN         13
+
+#define A2D_APTX_HD_VENDOR_ID               (0x000000D7)
+#define A2D_APTX_HD_CODEC_ID_BLUETOOTH      ((UINT16) 0x0024)
+#define A2D_APTX_HD_SAMPLERATE_44100        (0x20)
+#define A2D_APTX_HD_SAMPLERATE_48000        (0x10)
+#define A2D_APTX_HD_CHANNELS_STEREO         (0x02)
+#define A2D_APTX_HD_CHANNELS_MONO           (0x01)
+#define A2D_APTX_HD_ACL_SPRINT_RESERVED0    (0x00)
+#define A2D_APTX_HD_ACL_SPRINT_RESERVED1    (0x00)
+#define A2D_APTX_HD_ACL_SPRINT_RESERVED2    (0x00)
+#define A2D_APTX_HD_ACL_SPRINT_RESERVED3    (0x00)
+#define A2D_APTX_HD_OTHER_FEATURES_NONE     (0x00000000)
+#define A2D_APTX_HD_AV_AUDIO                (0x00)
+#define A2D_APTX_HD_CODEC_ID                (0xff)
+#define A2D_APTX_HD_CHANNEL                 (0x0001)
+#define A2D_APTX_HD_SAMPLERATE              (0x22)
+
+/*****************************************************************************
+**  Type Definitions
+*****************************************************************************/
+
+typedef struct {
+    UINT32 vendorId;
+    UINT16 codecId;         /* Codec ID for aptX HD */
+    UINT8  sampleRate;      /* Sampling Frequency */
+    UINT8  channelMode;     /* STEREO/DUAL/MONO */
+    UINT8 acl_sprint_reserved0;
+    UINT8 acl_sprint_reserved1;
+    UINT8 acl_sprint_reserved2;
+    UINT8 acl_sprint_reserved3;
+} tA2D_APTX_HD_CIE;
+
+typedef struct {
+    INT16 s16SamplingFreq;     /* 16k, 32k, 44.1k or 48k*/
+    INT16 s16ChannelMode;      /* mono, dual, streo or joint streo*/
+    UINT16 u16BitRate;
+    UINT16 *ps16NextPcmBuffer;
+    UINT8  *pu8Packet;
+    UINT8  *pu8NextPacket;
+    UINT16 u16PacketLength;
+    void* encoder;
+} A2D_APTX_HD_ENC_PARAMS;
+
+extern BOOLEAN isA2dAptXHdEnabled;
+
+/*****************************************************************************
+**  external function declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+extern UINT8 A2D_BldAptx_hdInfo(UINT8 media_type, tA2D_APTX_HD_CIE *p_ie,
+                             UINT8 *p_result);
+extern UINT8 A2D_ParsAptx_hdInfo(tA2D_APTX_HD_CIE *p_ie, UINT8 *p_info,
+                              BOOLEAN for_caps);
+extern int (*A2D_aptx_hd_encoder_init)(void);
+extern void (*A2D_aptx_hd_encoder_deinit)(void);
+extern UINT8 a2d_av_aptx_hd_cfg_in_cap(UINT8 *p_cfg, tA2D_APTX_HD_CIE *p_cap);
+extern BOOLEAN A2D_check_and_init_aptX_HD();
+extern void A2D_deinit_aptX_HD();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* A2D_APTX_HD_H */
diff --git a/stack/include/avct_api.h b/stack/include/avct_api.h
index c2713fd..350afdd 100644
--- a/stack/include/avct_api.h
+++ b/stack/include/avct_api.h
@@ -127,6 +127,20 @@
 
 /*******************************************************************************
 **
+** Function         AVCT_Init
+**
+** Description      This function is called to initialize the control block
+**                  for this layer.  It must be called before accessing any
+**                  other API functions for this layer.  It is typically called
+**                  once during the start up of the stack.
+**
+** Returns          void
+**
+*******************************************************************************/
+void AVCT_Init(void);
+
+/*******************************************************************************
+**
 ** Function         AVCT_Register
 **
 ** Description      This is the system level registration function for the
@@ -271,6 +285,59 @@
 *******************************************************************************/
 extern UINT16 AVCT_MsgReq(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR *p_msg);
 
+
+
+/******************************************************************************
+**
+** Function         AVCT_SetTraceLevel
+**
+** Description      Sets the trace level for AVCT. If 0xff is passed, the
+**                  current trace level is returned.
+**
+**                  Input Parameters:
+**                      new_level:  The level to set the AVCT tracing to:
+**                      0xff-returns the current setting.
+**                      0-turns off tracing.
+**                      >= 1-Errors.
+**                      >= 2-Warnings.
+**                      >= 3-APIs.
+**                      >= 4-Events.
+**                      >= 5-Debug.
+**
+** Returns          The new trace level or current trace level if
+**                  the input parameter is 0xff.
+**
+******************************************************************************/
+UINT8 AVCT_SetTraceLevel (UINT8 new_level);
+
+
+/*******************************************************************************
+**
+** Function         avct_get_peer_addr_by_ccb
+**
+**
+** Description      Return peer BD address on ccb index (or handle).
+**
+**
+**
+**
+** Returns          BD Address.
+**
+*******************************************************************************/
+extern BOOLEAN avct_get_peer_addr_by_ccb (UINT8 idx, BD_ADDR addr);
+
+/*******************************************************************************
+**
+** Function         AVCT_CheckIncomingConn
+**
+**
+** Description      Check if remote AVCTP incoming connection in progress
+**
+** Returns          TRUE if icoming connection is in progress,
+**
+*******************************************************************************/
+extern BOOLEAN AVCT_CheckIncomingConn(BD_ADDR peer_addr);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/stack/include/avdt_api.h b/stack/include/avdt_api.h
index e10faf0..f52420f 100644
--- a/stack/include/avdt_api.h
+++ b/stack/include/avdt_api.h
@@ -1,4 +1,10 @@
 /******************************************************************************
+ *  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ *  Not a contribution.
+ ******************************************************************************/
+
+/******************************************************************************
  *
  *  Copyright (C) 2002-2012 Broadcom Corporation
  *
@@ -47,6 +53,12 @@
 /* The index to access the codec type in codec_info[]. */
 #define AVDT_CODEC_TYPE_INDEX       2
 
+/* The index to access the vendorId in codec_info[]. */
+#define AVDT_VENDOR_ID_TYPE_INDEX    3
+
+/* The index to access the codecId in codec_info[]. */
+#define AVDT_CODEC_ID_TYPE_INDEX     7
+
 /* The size in bytes of a Adaptation Layer header. */
 #define AVDT_AL_HDR_SIZE         3
 
@@ -400,6 +412,7 @@
     UINT8               tsep;           /* SEP type */
     UINT8               media_type;     /* Media type */
     UINT16              nsc_mask;       /* Nonsupported protocol command messages */
+    UINT8               registration_id;/* All SCBs created during single registration will have same value.*/
 } tAVDT_CS;
 
 /* AVDT data option mask is used in the write request */
@@ -420,6 +433,20 @@
 
 /*******************************************************************************
 **
+** Function         AVDT_Init
+**
+** Description      This function is called to initialize the control block
+**                  for this layer.  It must be called before accessing any
+**                  other API functions for this layer.  It is typically called
+**                  once during the start up of the stack.
+**
+** Returns          void
+**
+*******************************************************************************/
+void AVDT_Init(void);
+
+/*******************************************************************************
+**
 ** Function         AVDT_Register
 **
 ** Description      This is the system level registration function for the
@@ -452,6 +479,32 @@
 
 /*******************************************************************************
 **
+** Function         AVDT_UpdateServiceBusyState
+**
+** Description      This function is used to set the service busy state
+**                  during outgoing connection to properly handle the
+**                  connections in upper layers.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void AVDT_UpdateServiceBusyState(BOOLEAN state);
+
+/*******************************************************************************
+**
+** Function         AVDT_GetServiceBusyState
+**
+** Description      This function is used to get the service busy state
+**
+**
+** Returns          outgoing connection in progress or not
+**
+*******************************************************************************/
+BOOLEAN AVDT_GetServiceBusyState(void);
+
+/*******************************************************************************
+**
 ** Function         AVDT_SINK_Activate
 **
 ** Description      Activate SEP of A2DP Sink. In Use parameter is adjusted.
@@ -894,6 +947,20 @@
 *******************************************************************************/
 extern UINT16 AVDT_GetSignalChannel(UINT8 handle, BD_ADDR bd_addr);
 
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+/*******************************************************************************
+**
+** Function         AVDT_GetStreamingDestChannel
+**
+** Description      Get the Dest L2CAP CID used by the stream channel.
+**
+** Returns          Destination CID.
+**
+*******************************************************************************/
+UINT16 AVDT_GetStreamingDestChannelId(UINT16 lcid);
+#endif
+
+
 /*******************************************************************************
 **
 ** Function         AVDT_SetMediaBuf
@@ -928,6 +995,17 @@
 extern UINT16 AVDT_SendReport(UINT8 handle, AVDT_REPORT_TYPE type,
                               tAVDT_REPORT_DATA *p_data);
 
+/*******************************************************************************
+**
+** Function         AVDT_UpdateMaxAvClients
+**
+** Description      Update max simultaneous AV connections supported
+**
+** Returns
+**
+*******************************************************************************/
+extern void AVDT_UpdateMaxAvClients(UINT8 num_clients);
+
 /******************************************************************************
 **
 ** Function         AVDT_SetTraceLevel
diff --git a/stack/include/avrc_api.h b/stack/include/avrc_api.h
index d6fa4d9..7245b6b 100644
--- a/stack/include/avrc_api.h
+++ b/stack/include/avrc_api.h
@@ -120,7 +120,6 @@
 #define AVRC_METADATA_RESP              0x0001
 
 
-
 /*****************************************************************************
 **  data type definitions
 *****************************************************************************/
@@ -641,6 +640,21 @@
 *******************************************************************************/
 extern tAVRC_STS AVRC_BldResponse( UINT8 handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_pkt);
 
+/*******************************************************************************
+**
+** Function         AVRC_BldBrowseResponse
+**
+** Description      This function builds the given AVRCP response to the given
+**                  GKI buffer
+**
+** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
+**                  Otherwise, the error code.
+**
+*******************************************************************************/
+tAVRC_STS AVRC_BldBrowseResponse( UINT8 handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_pkt);
+
+
+
 /**************************************************************************
 **
 ** Function         AVRC_IsValidAvcType
@@ -665,6 +679,18 @@
 *******************************************************************************/
 extern BOOLEAN AVRC_IsValidPlayerAttr(UINT8 attr);
 
+/*******************************************************************************
+**
+** Function         AVRC_CheckIncomingConn
+**
+** Description      Check if AVRC incoming connection in progress
+**
+**
+** Returns          returns TRUE if incoming connection in progress
+**
+*******************************************************************************/
+extern BOOLEAN AVRC_CheckIncomingConn(BD_ADDR peer_addr);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/stack/include/avrc_defs.h b/stack/include/avrc_defs.h
index cb6178c..0b6cf00 100644
--- a/stack/include/avrc_defs.h
+++ b/stack/include/avrc_defs.h
@@ -31,9 +31,12 @@
 *****************************************************************************/
 
 /* Profile revision numbers */
+#define AVRC_REV_INVALID    0x0000
 #define AVRC_REV_1_0        0x0100
 #define AVRC_REV_1_3        0x0103
 #define AVRC_REV_1_4        0x0104
+#define AVRC_REV_1_5        0x0105
+#define AVRC_REV_1_6        0x0106
 
 #define AVRC_PACKET_LEN             512 /* Per the spec, you must support 512 byte RC packets */
 
@@ -203,7 +206,7 @@
 #define AVRC_PDU_REGISTER_NOTIFICATION          0x31
 #define AVRC_PDU_REQUEST_CONTINUATION_RSP       0x40
 #define AVRC_PDU_ABORT_CONTINUATION_RSP         0x41
-/* added in 1.4 */
+/* added in 1.4 and above*/
 #define AVRC_PDU_SET_ABSOLUTE_VOLUME            0x50
 #define AVRC_PDU_SET_ADDRESSED_PLAYER           0x60
 #define AVRC_PDU_SET_BROWSED_PLAYER             0x70
@@ -211,6 +214,7 @@
 #define AVRC_PDU_CHANGE_PATH                    0x72
 #define AVRC_PDU_GET_ITEM_ATTRIBUTES            0x73
 #define AVRC_PDU_PLAY_ITEM                      0x74
+#define AVRC_PDU_GET_TOTAL_NUMBER_OF_ITEMS      0x75
 #define AVRC_PDU_SEARCH                         0x80
 #define AVRC_PDU_ADD_TO_NOW_PLAYING             0x90
 #define AVRC_PDU_GENERAL_REJECT                 0xA0
@@ -299,7 +303,8 @@
 #define AVRC_MEDIA_ATTR_ID_NUM_TRACKS            0x00000005
 #define AVRC_MEDIA_ATTR_ID_GENRE                 0x00000006
 #define AVRC_MEDIA_ATTR_ID_PLAYING_TIME          0x00000007        /* in miliseconds */
-#define AVRC_MAX_NUM_MEDIA_ATTR_ID               7
+#define AVRC_MEDIA_ATTR_ID_COVER_ART             0x00000008
+#define AVRC_MAX_NUM_MEDIA_ATTR_ID               8
 
 /* Define the possible values of play state
 */
@@ -846,7 +851,7 @@
 					      (a >= AVRC_PLAYER_SETTING_LOW_MENU_EXT)) ? TRUE : FALSE)
 
 #define AVRC_IS_VALID_MEDIA_ATTRIBUTE(a)    ((a >= AVRC_MEDIA_ATTR_ID_TITLE) && \
-                                             (a <= AVRC_MEDIA_ATTR_ID_PLAYING_TIME) ? TRUE : FALSE)
+                                             (a <= AVRC_MEDIA_ATTR_ID_COVER_ART) ? TRUE : FALSE)
 
 #define AVRC_IS_VALID_BATTERY_STATUS(a)    ((a <= AVRC_BATTERY_STATUS_FULL_CHARGE) ? TRUE : FALSE)
 
@@ -1094,7 +1099,7 @@
     UINT32      start_item;
     UINT32      end_item;
     UINT8       attr_count;
-    UINT32      *p_attr_list;
+    UINT32      attrs[AVRC_MAX_ELEM_ATTR_SIZE];
 } tAVRC_GET_ITEMS_CMD;
 
 /* ChangePath */
@@ -1105,7 +1110,7 @@
     UINT8       opcode;         /* Op Code (assigned by AVRC_BldCommand according to pdu) */
     UINT16      uid_counter;
     UINT8       direction;
-    tAVRC_UID   folder_uid;
+    UINT64      folder_uid;
 } tAVRC_CHG_PATH_CMD;
 
 /* GetItemAttrs */
@@ -1115,10 +1120,10 @@
     tAVRC_STS   status;
     UINT8       opcode;         /* Op Code (assigned by AVRC_BldCommand according to pdu) */
     UINT8       scope;
-    tAVRC_UID   uid;
+    UINT64      uid;
     UINT16      uid_counter;
     UINT8       attr_count;
-    UINT32      *p_attr_list;
+    UINT32      attrs[AVRC_MAX_ELEM_ATTR_SIZE];
 } tAVRC_GET_ATTRS_CMD;
 
 /* Search */
@@ -1137,7 +1142,7 @@
     tAVRC_STS   status;
     UINT8       opcode;         /* Op Code (assigned by AVRC_BldCommand according to pdu) */
     UINT8       scope;
-    tAVRC_UID   uid;
+    UINT64      uid;
     UINT16      uid_counter;
 } tAVRC_PLAY_ITEM_CMD;
 
@@ -1157,6 +1162,14 @@
     UINT8       pdu;
     tAVRC_STS   status;
     UINT8       opcode;         /* Op Code (assigned by AVRC_BldCommand according to pdu) */
+    UINT8       scope;
+} tAVRC_GET_TOTAL_ITEM_CMD;
+
+typedef struct
+{
+    UINT8       pdu;
+    tAVRC_STS   status;
+    UINT8       opcode;         /* Op Code (assigned by AVRC_BldCommand according to pdu) */
 } tAVRC_CMD;
 
 /* Continue and Abort */
@@ -1196,6 +1209,7 @@
     tAVRC_SEARCH_CMD            search;                 /* Search */
     tAVRC_PLAY_ITEM_CMD         play_item;              /* PlayItem */
     tAVRC_ADD_TO_PLAY_CMD       add_to_play;            /* AddToNowPlaying */
+    tAVRC_GET_TOTAL_ITEM_CMD    get_tot_item;           /* GetTotalNumberOfItems*/
 } tAVRC_COMMAND;
 
 /* GetCapability */
@@ -1300,6 +1314,7 @@
     tAVRC_ADDR_PLAYER_PARAM addr_player;
     UINT16                  uid_counter;
     UINT8                   volume;
+    UINT8                   evt;//For Available Player Changed Notification
 } tAVRC_NOTIF_RSP_PARAM;
 
 /* RegNotify */
@@ -1374,6 +1389,16 @@
     UINT32              num_items;
 } tAVRC_SEARCH_RSP;
 
+/* GetTotItems*/
+typedef struct
+{
+    UINT8               pdu;
+    tAVRC_STS           status;
+    UINT8               opcode;         /* Op Code (copied from avrc_cmd.opcode by AVRC_BldResponse user. invalid one to generate according to pdu) */
+    UINT16              uid_counter;
+    UINT32              num_items;
+} tAVRC_GET_TOT_ITEMS_RSP;
+
 typedef struct
 {
     UINT8       pdu;
@@ -1409,6 +1434,7 @@
     tAVRC_SEARCH_RSP                search;                 /* Search */
     tAVRC_RSP                       play_item;              /* PlayItem */
     tAVRC_RSP                       add_to_play;            /* AddToNowPlaying */
+    tAVRC_GET_TOT_ITEMS_RSP         get_tot_items;          /* GetTotalItems */
 } tAVRC_RESPONSE;
 
 #endif
diff --git a/stack/include/bt_types.h b/stack/include/bt_types.h
index ce98592..ebc1e00 100644
--- a/stack/include/bt_types.h
+++ b/stack/include/bt_types.h
@@ -20,6 +20,7 @@
 #define BT_TYPES_H
 
 #include <stdint.h>
+#include <stdio.h>
 #include <stdbool.h>
 #include <string.h>
 
@@ -731,6 +732,9 @@
 *******************************************************************************/
 static inline void bdcpy(BD_ADDR a, const BD_ADDR b)
 {
+    if (a ==  NULL || b == NULL)
+       return;
+
     int i;
 
     for (i = BD_ADDR_LEN; i != 0; i--)
diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h
index 360dd48..b806037 100644
--- a/stack/include/btm_api.h
+++ b/stack/include/btm_api.h
@@ -30,6 +30,7 @@
 #include "hcidefs.h"
 
 #include "smp_api.h"
+
 /*****************************************************************************
 **  DEVICE CONTROL and COMMON
 *****************************************************************************/
@@ -110,6 +111,21 @@
     UINT8   *p_param_buf;
 } tBTM_VSC_CMPL;
 
+/* Structure returned with HCI Raw Command complete callback */
+typedef struct
+{
+    UINT8  event_code;
+    UINT8  param_len;
+    UINT8   *p_param_buf;
+} tBTM_RAW_CMPL;
+
+typedef struct
+{
+    UINT16 adv_len;
+    UINT8 *adv_data_cache;
+} tBTM_BLE_INQ_DATA_CB;
+
+
 #define  BTM_VSC_CMPL_DATA_SIZE  (BTM_MAX_VENDOR_SPECIFIC_LEN + sizeof(tBTM_VSC_CMPL))
 /**************************************************
 **  Device Control and General Callback Functions
@@ -149,6 +165,11 @@
 */
 typedef void (tBTM_VSC_CMPL_CB) (tBTM_VSC_CMPL *p1);
 
+/* HCI RAW CMD callback function for notifying an application that a synchronous
+** BTM function is complete. The pointer contains the address of any returned data.
+*/
+typedef void (tBTM_RAW_CMPL_CB) (tBTM_RAW_CMPL *p1);
+
 /* Callback for apps to check connection and inquiry filters.
 ** Parameters are the BD Address of remote and the Dev Class of remote.
 ** If the app returns none zero, the connection or inquiry result will be dropped.
@@ -184,6 +205,7 @@
 #define BTM_BLE_MAX_CONNECTABLE      BTM_BLE_CONNECTABLE
 #define BTM_BLE_CONNECTABLE_MASK    (BTM_BLE_NON_CONNECTABLE | BTM_BLE_CONNECTABLE)
 
+#define BTM_BLE_ADV_STOP            2
 /* Inquiry modes
  * Note: These modes are associated with the inquiry active values (BTM_*ACTIVE) */
 #define BTM_INQUIRY_NONE            0
@@ -590,7 +612,7 @@
 #define BTM_BLE_EVT_DISC_ADV        0x02
 #define BTM_BLE_EVT_NON_CONN_ADV    0x03
 #define BTM_BLE_EVT_SCAN_RSP        0x04
-typedef UINT8 tBTM_BLE_EVT_TYPE;
+typedef UINT16 tBTM_BLE_EVT_TYPE;
 #endif
 
 /* These are the fields returned in each device's response to the inquiry.  It
@@ -607,12 +629,20 @@
     INT8        rssi;       /* Set to BTM_INQ_RES_IGNORE_RSSI if  not valid */
     UINT32      eir_uuid[BTM_EIR_SERVICE_ARRAY_SIZE];
     BOOLEAN     eir_complete_list;
+    UINT16      adv_data_len;
 #if (BLE_INCLUDED == TRUE)
     tBT_DEVICE_TYPE         device_type;
     UINT8       inq_result_type;
     UINT8       ble_addr_type;
     tBTM_BLE_EVT_TYPE       ble_evt_type;
     UINT8                   flag;
+    tBTM_BLE_INQ_DATA_CB    inq_data;
+    UINT8       pri_phy;
+    UINT8       sec_phy;
+    UINT8       adv_sid;
+    UINT16      periodic_adv_int;
+    UINT8       direct_addr_type;
+    BD_ADDR     direct_bda;
 #endif
 } tBTM_INQ_RESULTS;
 
@@ -835,7 +865,8 @@
 typedef struct
 {
     tBTM_BL_EVENT   event;  /* The event reported. */
-    UINT8           busy_level;/* when paging or inquiring, level is 10.
+    UINT8           busy_level;/* when paging or inquiring, level is between
+                                  17 to 21 as the max links can be 16.
                                 * Otherwise, the number of ACL links. */
     UINT8           busy_level_flags; /* Notifies actual inquiry/page activities */
 } tBTM_BL_UPDATE_DATA;
@@ -1594,13 +1625,14 @@
 #define BTM_LE_AUTH_REQ_MITM    SMP_AUTH_YN_BIT    /* 1 << 2 */
 typedef UINT8 tBTM_LE_AUTH_REQ;
 #define BTM_LE_SC_SUPPORT_BIT           SMP_SC_SUPPORT_BIT     /* (1 << 3) */
-#define BTM_LE_KP_SUPPORT_BIT           SMP_KP_SUPPORT_BIT     /* (1 << 4) */
+#define BTM_LE_KP_SUPPORT_BIT           SMP_KP_SUPPORT_BIT     /* (1 << 4) */`
+#define BTM_LE_H7_SUPPORT_BIT           SMP_H7_SUPPORT_BIT     /* (1 << 5) */`
 
-#define BTM_LE_AUTH_REQ_SC_ONLY         SMP_AUTH_SC_ENC_ONLY    /* 1 << 3 */
-#define BTM_LE_AUTH_REQ_SC_BOND         SMP_AUTH_SC_GB          /* 1001 */
-#define BTM_LE_AUTH_REQ_SC_MITM         SMP_AUTH_SC_MITM_NB     /* 1100 */
-#define BTM_LE_AUTH_REQ_SC_MITM_BOND    SMP_AUTH_SC_MITM_GB     /* 1101 */
-#define BTM_LE_AUTH_REQ_MASK            SMP_AUTH_MASK           /* 0x1D */
+#define BTM_LE_AUTH_REQ_SC_ONLY         SMP_AUTH_SC_ENC_ONLY    /* 00101000 */
+#define BTM_LE_AUTH_REQ_SC_BOND         SMP_AUTH_SC_GB          /* 00101001 */
+#define BTM_LE_AUTH_REQ_SC_MITM         SMP_AUTH_SC_MITM_NB     /* 00101100 */
+#define BTM_LE_AUTH_REQ_SC_MITM_BOND    SMP_AUTH_SC_MITM_GB     /* 00101101 */
+#define BTM_LE_AUTH_REQ_MASK            SMP_AUTH_MASK           /* 0x3D */
 
 /* LE security level */
 #define BTM_LE_SEC_NONE             SMP_SEC_NONE
@@ -1921,6 +1953,17 @@
 
 /*******************************************************************************
 **
+** Function         BTM_HCI_Reset
+**
+** Description      This function is called to send reset command to the controller.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTM_HCI_Reset (void);
+
+/*******************************************************************************
+**
 ** Function         BTM_IsDeviceUp
 **
 ** Description      This function is called to check if the device is up.
@@ -2038,6 +2081,18 @@
 
 /*******************************************************************************
 **
+** Function         BTM_Hci_Raw_Command
+**
+** Description      Send a HCI RAW started testingcommand to the controller.
+**
+*******************************************************************************/
+extern tBTM_STATUS BTM_Hci_Raw_Command(UINT16 opcode,
+                                                         UINT8 param_len,
+                                                         UINT8 *p_param_buf,
+                                                         tBTM_RAW_CMPL_CB *p_cb);
+
+/*******************************************************************************
+**
 ** Function         BTM_VendorSpecificCommand
 **
 ** Description      Send a vendor specific HCI command to the controller.
@@ -3769,7 +3824,7 @@
 ** Returns          pointer of EIR data
 **
 *******************************************************************************/
-extern UINT8 *BTM_CheckEirData( UINT8 *p_eir, UINT8 type, UINT8 *p_length );
+extern UINT8 *BTM_CheckEirData( UINT8 *p_eir, UINT8 type, UINT8 *p_length, UINT16 adv_data_len );
 
 /*******************************************************************************
 **
diff --git a/stack/include/btm_ble_api.h b/stack/include/btm_ble_api.h
index 0cc2e18..e065ae3 100644
--- a/stack/include/btm_ble_api.h
+++ b/stack/include/btm_ble_api.h
@@ -48,7 +48,25 @@
 
 #define BTM_BLE_UNKNOWN_EVT     0xff
 
+#define BTM_BLE_EXT_SCAN_RSP_EVT_MASK   0x08
+#define BTM_BLE_EXT_CONNECT_DIR_EVT_MASK   0x04
+#define BTM_BLE_EXT_LEGACY_ADV_MASK   0x10
+#define BTM_BLE_EXT_CONN_ADV_MASK   0x01
+#define BTM_BLE_EXT_ADV_EVT_DATA_MASK   0x60
+
+#define BTM_BLE_EXT_ADV_EVT_DATA_CMPL_MASK   0x00
+#define BTM_BLE_EXT_ADV_EVT_DATA_INCMPL_MASK   0x20
+#define BTM_BLE_EXT_ADV_EVT_DATA_INCMPL_TRUNC_MASK   0x40
+
 typedef UINT8 tBTM_BLE_EVT;
+
+#define BTM_BLE_EXT_CONNECT_EVT        0x0013
+#define BTM_BLE_EXT_CONNECT_DIR_EVT    0x001D
+#define BTM_BLE_EXT_DISCOVER_EVT       0x0012
+#define BTM_BLE_EXT_NON_CONNECT_EVT    0x0010
+#define BTM_BLE_EXT_CONNECT_LO_DUTY_DIR_EVT   0x0015
+typedef UINT16 tBTM_BLE_EXT_EVT;
+
 typedef UINT8 tBTM_BLE_CONN_MODE;
 
 typedef UINT32 tBTM_BLE_REF_VALUE;
@@ -357,7 +375,8 @@
 /*  Preferred maximum number of microseconds that the local Controller
     should use to transmit a single Link Layer Data Channel PDU. */
 #define BTM_BLE_DATA_TX_TIME_MIN     0x0148
-#define BTM_BLE_DATA_TX_TIME_MAX     0x0848
+#define BTM_BLE_DATA_TX_TIME_MAX_LEGACY     0x0848
+#define BTM_BLE_DATA_TX_TIME_MAX            0x4290
 
 /* adv tx power level */
 #define BTM_BLE_ADV_TX_POWER_MIN        0           /* minimum tx power */
@@ -367,6 +386,11 @@
 #define BTM_BLE_ADV_TX_POWER_MAX        4           /* maximum tx power */
 typedef UINT8 tBTM_BLE_ADV_TX_POWER;
 
+/* Subevent code for LE Connection Complete event */
+#if (BLE_PRIVACY_SPT == TRUE )
+#define BTM_BLE_ENHC_CONN_SUB_CODE 0x0A
+#endif
+
 /* adv tx power in dBm */
 typedef struct
 {
@@ -384,6 +408,12 @@
     UINT8 debug_logging_supported;
 }tBTM_BLE_VSC_CB;
 
+typedef struct
+{
+    UINT8 adv_inst_max;         /* max adv instance supported in controller */
+    UINT16 adv_data_len_max;
+}tBTM_BLE_ADV_EXT_CB;
+
 /* slave preferred connection interval range */
 typedef struct
 {
@@ -466,28 +496,48 @@
 }tBTM_BLE_ADV_DATA;
 
 #ifndef BTM_BLE_MULTI_ADV_MAX
+
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+#define BTM_BLE_MULTI_ADV_MAX   17 /* An extra instance for Extended adv in order to use the 0 inst_id*/
+#else
 #define BTM_BLE_MULTI_ADV_MAX   16 /* controller returned adv_inst_max should be less
                                       than this number */
 #endif
 
+#endif
+
 #define BTM_BLE_MULTI_ADV_INVALID   0
 
 #define BTM_BLE_MULTI_ADV_ENB_EVT           1
 #define BTM_BLE_MULTI_ADV_DISABLE_EVT       2
 #define BTM_BLE_MULTI_ADV_PARAM_EVT         3
 #define BTM_BLE_MULTI_ADV_DATA_EVT          4
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+#define BTM_BLE_EXTENDED_ADV_ENB_EVT        5
+#define BTM_BLE_EXTENDED_ADV_PARAM_EVT      6
+#endif
 typedef UINT8 tBTM_BLE_MULTI_ADV_EVT;
 
 #define BTM_BLE_MULTI_ADV_DEFAULT_STD 0
 
 typedef struct
 {
-    UINT16          adv_int_min;
-    UINT16          adv_int_max;
-    UINT8           adv_type;
+    UINT32          adv_int_min;
+    UINT32          adv_int_max;
+    UINT16           adv_type;
     tBTM_BLE_ADV_CHNL_MAP channel_map;
     tBTM_BLE_AFP    adv_filter_policy;
     tBTM_BLE_ADV_TX_POWER tx_power;
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    UINT8           pri_phy;
+    UINT8           sec_adv_max_skip;
+    UINT8           sec_adv_phy;
+    UINT8           adv_sid;
+    UINT8           scan_req_notf_enb;
+    UINT16          duration;
+    UINT8           max_ext_adv_evts;
+    UINT8           frag_pref;
+#endif
 }tBTM_BLE_ADV_PARAMS;
 
 typedef struct
@@ -511,6 +561,24 @@
     tBTM_BLE_MULTI_ADV_CBACK    *p_cback;
     void                        *p_ref;
     UINT8                       index;
+    UINT16                      len;
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    UINT16                      duration;
+    tBTM_BLE_EXT_EVT            evt_prop;
+
+    //for chained ext advs
+    UINT32                      adv_int_min;
+    UINT32                      adv_int_max;
+    UINT8                       channel_map;
+    UINT8                       adv_filter_policy;
+    UINT8                       tx_power;
+    UINT8                       pri_phy;
+    UINT8                       sec_adv_max_skip;
+    UINT8                       sec_adv_phy;
+    UINT8                       adv_sid;
+    UINT8                       scan_req_notf_enb;
+    UINT8                       own_addr_type;
+#endif
 }tBTM_BLE_MULTI_ADV_INST;
 
 typedef struct
@@ -526,6 +594,15 @@
     tBTM_BLE_MULTI_ADV_OPQ  op_q;
 }tBTM_BLE_MULTI_ADV_CB;
 
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+typedef struct
+{
+    UINT8     *set_ids;
+    UINT16    *durations;
+    UINT8     *max_adv_events;
+}tBTM_BLE_EXT_ADV_ENABLE_CB;
+#endif
+
 typedef UINT8 tGATT_IF;
 
 typedef void (tBTM_BLE_SCAN_THRESHOLD_CBACK)(tBTM_BLE_REF_VALUE ref_value);
@@ -1006,8 +1083,9 @@
 ** Returns          void
 **
 *******************************************************************************/
-extern void BTM_BleSetScanParams(tGATT_IF client_if, UINT32 scan_interval,
-                                 UINT32 scan_window, tBLE_SCAN_MODE scan_type,
+extern void BTM_BleSetScanParams(tGATT_IF client_if, UINT8 scan_phys, UINT32 scan_interval,
+                                 UINT32 scan_window, UINT16 scan_interval_coded,
+                                 UINT16 scan_window_coded, tBLE_SCAN_MODE scan_type,
                                  tBLE_SCAN_PARAM_SETUP_CBACK scan_setup_status_cback);
 
 /*******************************************************************************
@@ -1022,6 +1100,19 @@
 **
 *******************************************************************************/
 extern void BTM_BleGetVendorCapabilities(tBTM_BLE_VSC_CB *p_cmn_vsc_cb);
+
+/*******************************************************************************
+**
+** Function         BTM_BleGetAdvExtCapabilities
+**
+** Description      This function reads local LE features
+**
+** Parameters       p_cmn_vsc_cb : Locala LE capability structure
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTM_BleGetAdvExtCapabilities(tBTM_BLE_ADV_EXT_CB *p_ble_adv_ext_cb);
 /*******************************************************************************
 **
 ** Function         BTM_BleSetStorageConfig
@@ -1136,7 +1227,7 @@
 ** Returns          void
 **
 *******************************************************************************/
-extern tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT8 duration,
+extern tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT16 duration, UINT16 period,
                                   tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb);
 
 
@@ -1444,6 +1535,32 @@
 *******************************************************************************/
 extern void BTM_BleReadControllerFeatures(tBTM_BLE_CTRL_FEATURES_CBACK  *p_vsc_cback);
 
+/******************************************************************************
+**
+** Function         BTM_BleReadExtAdvControllerFeatures
+**
+** Description      Reads BLE specific controller features
+**
+** Parameters:      tBTM_BLE_CTRL_FEATURES_CBACK : Callback to notify when features are read
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTM_BleReadExtAdvControllerFeatures(tBTM_BLE_CTRL_FEATURES_CBACK  *p_vsc_cback);
+
+/******************************************************************************
+**
+** Function         BTM_BleGetAvailableMAInstance
+**
+** Description      Gets Available Multi Adv instance
+**
+** Parameters:      void
+**
+** Returns          Multi advertisement instance id
+**
+*******************************************************************************/
+extern UINT8 BTM_BleGetAvailableMAInstance(void);
+
 /*******************************************************************************
 **
 ** Function         BTM_CheckAdvData
@@ -1457,7 +1574,7 @@
 ** Returns          pointer of ADV data
 **
 *******************************************************************************/
-extern  UINT8 *BTM_CheckAdvData( UINT8 *p_adv, UINT8 type, UINT8 *p_length);
+extern  UINT8 *BTM_CheckAdvData( UINT8 *p_adv, UINT8 type, UINT8 *p_length, UINT16 adv_data_len);
 
 /*******************************************************************************
 **
@@ -1647,6 +1764,21 @@
 *******************************************************************************/
 void BTM_BleReceiverTest(UINT8 rx_freq, tBTM_CMPL_CB *p_cmd_cmpl_cback);
 
+/*******************************************************************************
+**
+** Function         BTM_BleEnhReceiverTest
+**
+** Description      This function is called to start the LE Enhanced Receiver
+**                  test
+**
+** Parameter        rx_freq - Frequency Range
+**                  phy - Phy to be used
+**                  mod_index - Modulation index
+**                  p_cmd_cmpl_cback - Command Complete callback
+**
+*******************************************************************************/
+void BTM_BleEnhReceiverTest(UINT8 rx_freq, UINT8 phy, UINT8 mod_index,
+                              tBTM_CMPL_CB *p_cmd_cmpl_cback);
 
 /*******************************************************************************
 **
@@ -1665,6 +1797,23 @@
 
 /*******************************************************************************
 **
+** Function         BTM_BleEnhTransmitterTest
+**
+** Description      This function is called to start the LE Enhanced Transmitter test
+**
+** Parameter        tx_freq - Frequency Range
+**                  test_data_len - Length in bytes of payload data in each packet
+**                  packet_payload - Pattern to use in the payload
+**                  phy - Phy to be used
+**                  p_cmd_cmpl_cback - Command Complete callback
+**
+*******************************************************************************/
+void BTM_BleEnhTransmitterTest(UINT8 tx_freq, UINT8 test_data_len,
+                                 UINT8 packet_payload, UINT8 phy,
+                                 tBTM_CMPL_CB *p_cmd_cmpl_cback);
+
+/*******************************************************************************
+**
 ** Function         BTM_BleTestEnd
 **
 ** Description      This function is called to stop the in-progress TX or RX test
@@ -1790,7 +1939,7 @@
 **
 *******************************************************************************/
 extern tBTM_STATUS BTM_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
-                                    tBTM_BLE_AD_MASK data_mask,
+                                    tBTM_BLE_AD_MASK data_mask, UINT8 frag_pref,
                                     tBTM_BLE_ADV_DATA *p_data);
 
 /*******************************************************************************
@@ -1887,6 +2036,68 @@
 *******************************************************************************/
 extern tBTM_STATUS BTM_SetBleDataLength(BD_ADDR bd_addr, UINT16 tx_pdu_length);
 
+
+
+/*******************************************************************************
+**
+** Function         BTM_GetRemoteDeviceName
+**
+** Description      This function is called to get the dev name of remote device
+**                  from NV
+**
+** Returns          TRUE if success; otherwise failed.
+**
+*******************************************************************************/
+extern BOOLEAN BTM_GetRemoteDeviceName(BD_ADDR bda, BD_NAME bdname);
+/*******************************************************************************
+**
+** Function         BTM_SetBlePhy
+**
+** Description      This function is called to set BLE Tx and Rx Phy
+**
+** Returns          BTM_SUCCESS if success; otherwise failed.
+**
+*******************************************************************************/
+extern tBTM_STATUS BTM_SetBlePhy(BD_ADDR bd_addr, UINT8 all_phy, UINT8 tx_phy,
+                                 UINT8 rx_phy, UINT16 phy_options);
+
+/*******************************************************************************
+**
+** Function         BTM_SetDefaultBlePhy
+**
+** Description      This function is to set default BLE tx and rx PHY
+**
+** Returns          BTM_SUCCESS if success; otherwise failed.
+**
+*******************************************************************************/
+tBTM_STATUS BTM_SetDefaultBlePhy(UINT8 all_phy, UINT8 tx_phy, UINT8 rx_phy);
+
+
+/*******************************************************************************
+**
+** Function         BTM_BleWriteExtendedAdvData
+**
+** Description      This function configure a Multi-ADV instance with the specified
+**                  adv data or scan response data.
+**
+** Parameters       inst_id: adv instance ID
+**                  is_scan_rsp: is this scan response. if no, set as adv data.
+**                  data_mask: adv data mask.
+**                  p_data: pointer to the adv data structure.
+**                  operation:
+**                  0x00: Intermediate fragment
+**                  0x01: first fragment
+**                  0x02: Last fragment
+**                  0x03: complete data, ctrlr fragmentation permitted
+**                  0x04: complete data, ctrlr fragmentation not permitted
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTM_STATUS BTM_BleWriteExtendedAdvData (UINT8 inst_id, BOOLEAN is_scan_rsp,
+                                    tBTM_BLE_AD_MASK data_mask,
+                                    UINT8 operation, UINT8 frag_pref,
+                                    tBTM_BLE_ADV_DATA *p_data);
 #ifdef __cplusplus
 }
 #endif
diff --git a/stack/include/btu.h b/stack/include/btu.h
index d0415f9..bf617d0 100644
--- a/stack/include/btu.h
+++ b/stack/include/btu.h
@@ -50,6 +50,7 @@
   void *context;
 } command_status_hack_t;
 
+void bte_ssr_cleanup(int reason);
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/stack/include/gap_api.h b/stack/include/gap_api.h
index e1be352..394fbd3 100644
--- a/stack/include/gap_api.h
+++ b/stack/include/gap_api.h
@@ -56,6 +56,7 @@
 #define GAP_EVT_CONN_CONGESTED      0x0103
 #define GAP_EVT_CONN_UNCONGESTED    0x0104
 #define GAP_EVT_TX_EMPTY            0x0105
+#define GAP_EVT_TX_DONE             0x0106
 
 /* Values for 'chan_mode_mask' field */
 /* GAP_ConnOpen() - optional channels to negotiate */
diff --git a/stack/include/hcidefs.h b/stack/include/hcidefs.h
index 71d5046..59771e8 100644
--- a/stack/include/hcidefs.h
+++ b/stack/include/hcidefs.h
@@ -27,6 +27,7 @@
 #define HCI_PROTO_VERSION_4_0 0x06      /* Version for BT spec 4.0          */
 #define HCI_PROTO_VERSION_4_1 0x07      /* Version for BT spec 4.1          */
 #define HCI_PROTO_VERSION_4_2 0x08      /* Version for BT spec 4.2          */
+#define HCI_PROTO_VERSION_5_0 0x09      /* Version for BT spec 5.0          */
 
 /*
 **  Definitions for HCI groups
@@ -312,6 +313,7 @@
 #define HCI_BLE_WRITE_ADV_ENABLE        (0x000A | HCI_GRP_BLE_CMDS)
 #define HCI_BLE_WRITE_SCAN_PARAMS       (0x000B | HCI_GRP_BLE_CMDS)
 #define HCI_BLE_WRITE_SCAN_ENABLE       (0x000C | HCI_GRP_BLE_CMDS)
+
 #define HCI_BLE_CREATE_LL_CONN          (0x000D | HCI_GRP_BLE_CMDS)
 #define HCI_BLE_CREATE_CONN_CANCEL      (0x000E | HCI_GRP_BLE_CMDS)
 #define HCI_BLE_READ_WHITE_LIST_SIZE    (0x000F | HCI_GRP_BLE_CMDS)
@@ -348,6 +350,30 @@
 #define HCI_BLE_READ_RESOLVABLE_ADDR_LOCAL  (0x002C | HCI_GRP_BLE_CMDS)
 #define HCI_BLE_SET_ADDR_RESOLUTION_ENABLE  (0x002D | HCI_GRP_BLE_CMDS)
 #define HCI_BLE_SET_RAND_PRIV_ADDR_TIMOUT   (0x002E | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_SET_PRIVACY_MODE            (0x004E | HCI_GRP_BLE_CMDS)
+
+#define HCI_BLE_SET_DEFAULT_PHY_RATE        (0x0031 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_SET_PHY_RATE                (0x0032 | HCI_GRP_BLE_CMDS)
+
+#define HCI_BLE_ENH_RECEIVER_TEST           (0x0033 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_ENH_TRANSMITTER_TEST        (0x0034 | HCI_GRP_BLE_CMDS)
+
+/* BLE ADV EXTENSION COMMANDS */
+#define HCI_BLE_WRITE_EXTENDED_ADV_RPA      (0x0035 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_WRITE_EXTENDED_ADV_PARAMS   (0x0036 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_WRITE_EXTENDED_ADV_DATA     (0x0037 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_WRITE_EXTENDED_SCAN_RSP_DATA (0x0038 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_WRITE_EXTENDED_ADV_ENABLE   (0x0039 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_NUM_ADV_SETS           (0x003B | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_MAX_ADV_LENGTH         (0x003A | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_WRITE_EXT_SCAN_PARAMS       (0x0041 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_WRITE_EXT_SCAN_ENABLE       (0x0042 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_EXT_CREATE_LL_CONN          (0x0043 | HCI_GRP_BLE_CMDS)
+
+#define BTM_BLE_EXT_ADV_INT_FRAG            0x00
+#define BTM_BLE_EXT_ADV_FIRST_FRAG          0x01
+#define BTM_BLE_EXT_ADV_LAST_FRAG           0x02
+#define BTM_BLE_EXT_ADV_COMPLETE           0x03
 
 /* LE Get Vendor Capabilities Command OCF */
 #define HCI_BLE_VENDOR_CAP_OCF    (0x0153 | HCI_GRP_VENDOR_SPECIFIC)
@@ -372,6 +398,14 @@
 
 /* Controller debug info OCF */
 #define HCI_CONTROLLER_DEBUG_INFO_OCF     (0x015B | HCI_GRP_VENDOR_SPECIFIC)
+/* SOC Logging OCF */
+#define HCI_VS_HOST_LOG_OPCODE    (0x0017 | HCI_GRP_VENDOR_SPECIFIC)
+
+/* VOIP Network Wifi OCF */
+#define HCI_VSC_VOIP_NETWORK_WIFI_OCF   (0x001C | HCI_GRP_VENDOR_SPECIFIC)
+
+/* subcode for VOIP Network Wifi */
+#define HCI_VSC_SUBCODE_VOIP_NETWORK_WIFI               0x01
 
 /* subcode for multi adv feature */
 #define BTM_BLE_MULTI_ADV_SET_PARAM                     0x01
@@ -705,6 +739,14 @@
 #define HCI_BLE_DATA_LENGTH_CHANGE_EVT      0x07
 #define HCI_BLE_ENHANCED_CONN_COMPLETE_EVT  0x0a
 #define HCI_BLE_DIRECT_ADV_EVT              0x0b
+#define HCI_BLE_PHY_UPDATE_EVT              0x0c
+#if (defined BLE_EXTENDED_ADV_SUPPORT && BLE_EXTENDED_ADV_SUPPORT == TRUE)
+#define HCI_BLE_EXT_ADV_PKT_RPT_EVT         0x0d
+#define HCI_BLE_SCAN_TIMEOUT_EVT            0x11
+#define HCI_BLE_EXT_ADV_TERMINATED_EVT      0x12
+#endif
+
+
 
 /* Definitions for LE Channel Map */
 #define HCI_BLE_CHNL_MAP_SIZE               5
@@ -1442,7 +1484,8 @@
 #define HCI_EXT_FEATURES_PAGE_0     0       /* Extended Feature Page 0 (regular features) */
 #define HCI_EXT_FEATURES_PAGE_1     1       /* Extended Feature Page 1 */
 #define HCI_EXT_FEATURES_PAGE_2     2       /* Extended Feature Page 2 */
-#define HCI_EXT_FEATURES_PAGE_MAX   HCI_EXT_FEATURES_PAGE_2
+#define HCI_EXT_FEATURES_PAGE_3     3       /* Extended Feature Page 3 */
+#define HCI_EXT_FEATURES_PAGE_MAX   HCI_EXT_FEATURES_PAGE_3
 
 #define HCI_FEATURE_BYTES_PER_PAGE      8
 
@@ -1783,6 +1826,17 @@
 #define HCI_LE_FEATURE_DATA_LEN_EXT_OFF        0
 #define HCI_LE_DATA_LEN_EXT_SUPPORTED(x) ((x)[HCI_LE_FEATURE_DATA_LEN_EXT_OFF] & HCI_LE_FEATURE_DATA_LEN_EXT_MASK)
 
+/* 2Mbps support */
+#define HCI_LE_FEATURE_TWO_MBPS_MASK           0x01
+#define HCI_LE_FEATURE_TWO_MBPS                1
+#define HCI_LE_TWO_MBPS_SUPPORTED(x) ((x)[HCI_LE_FEATURE_TWO_MBPS] & HCI_LE_FEATURE_TWO_MBPS_MASK)
+
+/* Advertisement Length Extensions  */
+#define HCI_LE_FEATURE_ADV_EXT_MASK            0x10
+#define HCI_LE_FEATURE_ADV_EXT_OFF             1
+#define HCI_LE_ADV_EXTENSION_SUPPORTED(x) ((x)[HCI_LE_FEATURE_ADV_EXT_OFF] & HCI_LE_FEATURE_ADV_EXT_MASK)
+
+
 /*
 **   Local Supported Commands encoding
 */
@@ -2605,5 +2659,11 @@
 #define HCI_SUPP_COMMANDS_LE_RC_CONN_PARAM_UPD_NEG_RPY_OFF           33
 #define HCI_LE_RC_CONN_PARAM_UPD_NEG_RPY_SUPPORTED(x)      ((x)[HCI_SUPP_COMMANDS_LE_RC_CONN_PARAM_UPD_NEG_RPY_OFF] & HCI_SUPP_COMMANDS_RLE_RC_CONN_PARAM_UPD_NEG_RPY_MASK)
 
+/* support for LE privacy mode command (byte 39 bit 2)*/
+#define HCI_SUPP_COMMANDS_LE_SET_PRIVACY_MODE_MASK          0x04
+#define HCI_SUPP_COMMANDS_LE_SET_PRIVACY_MODE_OFF           39
+#define HCI_LE_SET_PRIVACY_MODE_SUPPORTED(x)      ((x)[HCI_SUPP_COMMANDS_LE_SET_PRIVACY_MODE_OFF] & HCI_SUPP_COMMANDS_LE_SET_PRIVACY_MODE_MASK)
+
+
 #endif
 
diff --git a/stack/include/hcimsgs.h b/stack/include/hcimsgs.h
index 30d861f..ae2f966 100644
--- a/stack/include/hcimsgs.h
+++ b/stack/include/hcimsgs.h
@@ -494,6 +494,10 @@
 #define HCI_DELETE_KEY_ALL_FLAG_OFF     6
                                                                 /* Delete Stored Key */
 
+extern BOOLEAN btsnd_hcic_reset(UINT8 local_controller_id);    /* Reset */
+
+#define HCIC_PARAM_SIZE_RESET           0                       /* Reset */
+
                                                                 /* Change Local Name */
 extern BOOLEAN btsnd_hcic_change_name(BD_NAME name);
 
@@ -517,6 +521,8 @@
 
 #define HCIC_WRITE_PARAM3_PARAM_OFF      0
 
+#define HCIC_PARAM_SIZE_WRITE_PARAM4     4
+
 #define HCIC_PARAM_SIZE_SET_AFH_CHANNELS    10
 
 extern BOOLEAN btsnd_hcic_write_pin_type(UINT8 type);                   /* Write PIN Type */
@@ -630,6 +636,8 @@
 #define HCID_HEADER_SIZE      4
 
 #define HCID_GET_SCO_LEN(p)  (*((UINT8 *)((p) + 1) + p->offset + 2))
+extern void btsnd_hcic_raw_cmd (void *buffer, UINT16 opcode, UINT8 len,
+                                 UINT8 *p_data, void *p_cmd_cplt_cback);
 
 extern void btsnd_hcic_vendor_spec_cmd (void *buffer, UINT16 opcode,
                                         UINT8 len, UINT8 *p_data,
@@ -651,8 +659,13 @@
 #define HCIC_PARAM_SIZE_WRITE_ADV_ENABLE        1
 #define HCIC_PARAM_SIZE_BLE_WRITE_SCAN_PARAM    7
 #define HCIC_PARAM_SIZE_BLE_WRITE_SCAN_ENABLE   2
+
+#define HCIC_PARAM_SIZE_BLE_WRITE_EXT_SCAN_PARAM    8
+#define HCIC_PARAM_SIZE_BLE_WRITE_EXT_SCAN_ENABLE   6
+
 #define HCIC_PARAM_SIZE_BLE_CREATE_LL_CONN      25
 #define HCIC_PARAM_SIZE_BLE_CREATE_CONN_CANCEL  0
+#define HCIC_PARAM_SIZE_BLE_EXT_CREATE_LL_CONN  26
 #define HCIC_PARAM_SIZE_CLEAR_WHITE_LIST        0
 #define HCIC_PARAM_SIZE_ADD_WHITE_LIST          7
 #define HCIC_PARAM_SIZE_REMOVE_WHITE_LIST       7
@@ -674,6 +687,7 @@
 
 #define HCIC_PARAM_SIZE_BLE_ADD_DEV_RESOLVING_LIST      (7 + HCIC_BLE_IRK_SIZE * 2)
 #define HCIC_PARAM_SIZE_BLE_RM_DEV_RESOLVING_LIST       7
+#define HCIC_PARAM_SIZE_BLE_SET_PRIVACY_MODE            8
 #define HCIC_PARAM_SIZE_BLE_CLEAR_RESOLVING_LIST        0
 #define HCIC_PARAM_SIZE_BLE_READ_RESOLVING_LIST_SIZE    0
 #define HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_PEER   7
@@ -682,6 +696,18 @@
 #define HCIC_PARAM_SIZE_BLE_SET_RAND_PRIV_ADDR_TIMOUT   2
 #define HCIC_PARAM_SIZE_BLE_SET_DATA_LENGTH             6
 #define HCIC_PARAM_SIZE_BLE_WRITE_EXTENDED_SCAN_PARAM  11
+#define HCIC_PARAM_SIZE_BLE_WRITE_DEFAULT_PHY          3
+#define HCIC_PARAM_SIZE_BLE_WRITE_PHY                  7
+
+#define HCIC_PARAM_SIZE_BLE_WRITE_EXTENDED_ADV_PARAMS  25
+#define HCIC_PARAM_SIZE_BLE_WRITE_EXTENDED_ADV_DATA    251
+#define HCIC_PARAM_SIZE_BLE_WRITE_EXTENDED_SCAN_RSP    251
+#define HCIC_PARAM_SIZE_WRITE_EXTENDED_ADV_ENABLE      2
+#define HCIC_PARAM_SIZE_WRITE_EXTENDED_ADV_RPA         7
+
+#define HCIC_SCAN_PHY_LE_1M         1
+#define HCIC_SCAN_PHY_LE_CODED      4
+#define HCIC_SCAN_PHY_LE_1M_CODED   5
 
 /* ULP HCI command */
 extern BOOLEAN btsnd_hcic_ble_set_evt_mask (BT_EVENT_MASK event_mask);
@@ -757,8 +783,14 @@
 
 extern BOOLEAN btsnd_hcic_ble_receiver_test(UINT8 rx_freq);
 
+extern BOOLEAN btsnd_hcic_ble_enh_receiver_test(UINT8 rx_freq, UINT8 phy, UINT8 mod_index);
+
 extern BOOLEAN btsnd_hcic_ble_transmitter_test(UINT8 tx_freq, UINT8 test_data_len,
                                                UINT8 payload);
+
+extern BOOLEAN btsnd_hcic_ble_enh_transmitter_test(UINT8 tx_freq, UINT8 test_data_len,
+                                               UINT8 payload, UINT8 phy);
+
 extern BOOLEAN btsnd_hcic_ble_test_end(void);
 
 #if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
@@ -785,6 +817,8 @@
 extern BOOLEAN btsnd_hcic_ble_rm_device_resolving_list (UINT8 addr_type_peer,
                                                                 BD_ADDR bda_peer);
 
+extern BOOLEAN btsnd_hcic_ble_set_privacy_mode (UINT8 addr_type_peer, BD_ADDR bda_peer, UINT8 privacy_type);
+
 extern BOOLEAN btsnd_hcic_ble_clear_resolving_list (void);
 
 extern BOOLEAN btsnd_hcic_ble_read_resolvable_addr_peer (UINT8 addr_type_peer,
@@ -797,6 +831,54 @@
 
 extern BOOLEAN btsnd_hcic_ble_set_rand_priv_addr_timeout (UINT16 rpa_timout);
 
+extern BOOLEAN btsnd_hcic_ble_set_default_data_rate(UINT8 all_phy, UINT8 tx_phy, UINT8 rx_phy);
+
+extern BOOLEAN btsnd_hcic_ble_set_data_rate(UINT16 handle, UINT8 all_phy, UINT8 tx_phy,
+                                            UINT8 rx_phy, UINT16 phy_options);
+
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+extern BOOLEAN btsnd_hcic_ble_set_extended_adv_params (UINT8 set_id, UINT16 event_properties,
+                                              UINT32 adv_int_min, UINT32 adv_int_max,
+                                              UINT8 channel_map, UINT8 addr_type_own,
+                                              UINT8 addr_type_dir, BD_ADDR direct_bda,
+                                              UINT8 adv_filter_policy, UINT8 adv_tx_power,
+                                              UINT8 primary_adv_phy, UINT8 secondary_max_skip,
+                                              UINT8 secondary_adv_phy, UINT8 advertising_sid,
+                                              UINT8 scan_req_not_enb);
+
+extern BOOLEAN btsnd_hcic_ble_set_extended_adv_data (UINT8 set_id, UINT8 operation, UINT8 fragment_pref,
+                                                     UINT8 data_len, UINT8 *p_data);
+
+extern BOOLEAN btsnd_hcic_ble_set_extended_scan_rsp_data (UINT8 set_id, UINT8 operation, UINT8 fragement_pref,
+                                                          UINT8 data_len, UINT8 *p_scan_rsp);
+
+extern BOOLEAN btsnd_hcic_ble_set_extended_adv_enable (UINT8 adv_enable, UINT8 num_sets, UINT8* handles,
+                                            UINT16* durations, UINT8* max_adv_events);
+
+extern BOOLEAN btsnd_hcic_ble_read_num_adv_sets (void);
+
+extern BOOLEAN btsnd_hcic_ble_read_extended_max_adv_len (void);
+
+extern BOOLEAN btsnd_hcic_ble_write_extended_rpa (UINT8 set_id, BD_ADDR rpa);
+
+extern BOOLEAN btsnd_hcic_ble_set_extended_scan_params (UINT8 scan_phys,
+                                                        UINT8 scan_type,
+                                                        UINT16 scan_int, UINT16 scan_win,
+                                                        UINT16 scan_int_coded, UINT16 scan_win_coded,
+                                                        UINT8 addr_type_own, UINT8 scan_filter_policy);
+
+extern BOOLEAN btsnd_hcic_ble_set_extended_scan_enable (UINT8 scan_enable, UINT8 duplicate,
+                                                        UINT16 duraton, UINT16 period);
+
+extern BOOLEAN btsnd_hcic_ble_ext_create_ll_conn (UINT8 ini_phy, UINT16 scan_int, UINT16 scan_win,
+                                                  UINT8 init_filter_policy,
+                                                  UINT8 addr_type_peer, BD_ADDR bda_peer,
+                                                  UINT8 addr_type_own,
+                                                  UINT16 conn_int_min, UINT16 conn_int_max,
+                                                  UINT16 conn_latency, UINT16 conn_timeout,
+                                                  UINT16 min_ce_len, UINT16 max_ce_len);
+#endif
+
 #endif /* BLE_INCLUDED */
 
 extern BOOLEAN btsnd_hcic_read_authenticated_payload_tout(UINT16 handle);
diff --git a/stack/include/l2c_api.h b/stack/include/l2c_api.h
index e8b21fe..518af3a 100644
--- a/stack/include/l2c_api.h
+++ b/stack/include/l2c_api.h
@@ -178,6 +178,7 @@
     UINT16  credits;
 } tL2CAP_LE_CFG_INFO;
 
+
 /* L2CAP channel configured field bitmap */
 #define L2CAP_CH_CFG_MASK_MTU           0x0001
 #define L2CAP_CH_CFG_MASK_QOS           0x0002
@@ -585,6 +586,19 @@
 *******************************************************************************/
 extern UINT8 L2CA_DataWrite (UINT16 cid, BT_HDR *p_data);
 
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+/*******************************************************************************
+**
+** Function         L2CA_GetDestChannelID
+**
+** Description      Higher layers call this function to fetch destination channel id.
+**
+** Returns          Destination Channel ID
+**
+*******************************************************************************/
+UINT16 L2CA_GetDestChannelID (UINT16 cid);
+#endif
+
 /*******************************************************************************
 **
 ** Function         L2CA_Ping
@@ -881,6 +895,21 @@
 *******************************************************************************/
 extern UINT8 L2CA_GetChnlFcrMode (UINT16 lcid);
 
+#if (defined(LE_L2CAP_CFC_INCLUDED) && (LE_L2CAP_CFC_INCLUDED == TRUE))
+/*******************************************************************************
+**
+**  Function         L2CA_LE_SetFlowControlCredits
+**
+**  Description      Set flow control credits
+**
+**  Parameters:      Local CID,Credits to set
+**
+**  Return value:    TRUE if flow control set,FALSE otherwise
+**
+*******************************************************************************/
+
+extern BOOLEAN L2CA_LE_SetFlowControlCredits (UINT16 cid, UINT16 credits);
+#endif
 
 /*******************************************************************************
 **
diff --git a/stack/include/port_api.h b/stack/include/port_api.h
index f24887b..66c6202 100644
--- a/stack/include/port_api.h
+++ b/stack/include/port_api.h
@@ -301,6 +301,19 @@
 *******************************************************************************/
 extern int PORT_SetEventMask (UINT16 port_handle, UINT32 mask);
 
+/*******************************************************************************
+**
+** Function         PORT_GetRemoteMtu
+**
+** Description      This function feteches remote mtu from port
+**
+** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
+**
+** Returns:         UINT16     - Maximum rfcomm frame size that can be
+**                               transmitted to the peer
+**
+*******************************************************************************/
+extern UINT16 PORT_GetRemoteMtu (UINT16 handle);
 
 /*******************************************************************************
 **
diff --git a/stack/include/sdp_api.h b/stack/include/sdp_api.h
index 16f2dbc..20b47fd 100644
--- a/stack/include/sdp_api.h
+++ b/stack/include/sdp_api.h
@@ -676,4 +676,17 @@
 *******************************************************************************/
 BOOLEAN SDP_FindServiceUUIDInRec(tSDP_DISC_REC *p_rec, tBT_UUID *p_uuid);
 
+/*********************************************************************************
+**
+** Function         SDP_Dev_Blacklisted_For_Avrcp15
+**
+** Description      This function is called to know is local Avrcp Version
+**                  1.3 as local Avrcp version is send as 1.3 for black listed
+**                  devices
+**
+** Returns          TRUE if AVRCP local Avrcp Version 1.3 else FALSE
+**
+********************************************************************************/
+BOOLEAN SDP_Dev_Blacklisted_For_Avrcp15 (BD_ADDR addr);
+
 #endif  /* SDP_API_H */
diff --git a/stack/include/sdpdefs.h b/stack/include/sdpdefs.h
index a4d6cc2..44d87e7 100644
--- a/stack/include/sdpdefs.h
+++ b/stack/include/sdpdefs.h
@@ -281,9 +281,6 @@
 #define UUID_CODEC_MSBC                         0x0002   /* mSBC */
 #endif
 
-#define UUID_HF_IND_ENHANCED_DRIVER_SAFETY      0x0001   /* Assigned number for Enhanced Safety */
-#define UUID_HF_IND_BATTERY_LEVEL_STATUS        0x0002   /* Assigned number for Battery Status */
-
 /* Define all the 'Descriptor Type' values.
 */
 #define  NULL_DESC_TYPE                     0
diff --git a/stack/include/smp_api.h b/stack/include/smp_api.h
index 87f526d..6d77d7f 100644
--- a/stack/include/smp_api.h
+++ b/stack/include/smp_api.h
@@ -146,8 +146,9 @@
 #define SMP_AUTH_YN_BIT         (1 << 2)
 #define SMP_SC_SUPPORT_BIT      (1 << 3)
 #define SMP_KP_SUPPORT_BIT      (1 << 4)
+#define SMP_H7_SUPPORT_BIT      (1 << 5)
 
-#define SMP_AUTH_MASK    (SMP_AUTH_GEN_BOND|SMP_AUTH_YN_BIT|SMP_SC_SUPPORT_BIT|SMP_KP_SUPPORT_BIT)
+#define SMP_AUTH_MASK    (SMP_AUTH_GEN_BOND|SMP_AUTH_YN_BIT|SMP_SC_SUPPORT_BIT|SMP_KP_SUPPORT_BIT|SMP_H7_SUPPORT_BIT)
 
 #define SMP_AUTH_BOND           SMP_AUTH_GEN_BOND
 
@@ -164,16 +165,16 @@
 #define SMP_AUTH_GB_IOCAP       (SMP_AUTH_GEN_BOND | SMP_AUTH_YN_BIT)
 
 /* Secure Connections, no MITM, no Bonding */
-#define SMP_AUTH_SC_ENC_ONLY    (SMP_SC_SUPPORT_BIT)
+#define SMP_AUTH_SC_ENC_ONLY    (SMP_SC_SUPPORT_BIT | SMP_H7_SUPPORT_BIT)
 
 /* Secure Connections, no MITM, Bonding */
-#define SMP_AUTH_SC_GB          (SMP_SC_SUPPORT_BIT | SMP_AUTH_GEN_BOND)
+#define SMP_AUTH_SC_GB          (SMP_SC_SUPPORT_BIT | SMP_AUTH_GEN_BOND | SMP_H7_SUPPORT_BIT)
 
 /* Secure Connections, MITM, no Bonding */
-#define SMP_AUTH_SC_MITM_NB     (SMP_SC_SUPPORT_BIT | SMP_AUTH_YN_BIT | SMP_AUTH_NO_BOND)
+#define SMP_AUTH_SC_MITM_NB     (SMP_SC_SUPPORT_BIT | SMP_AUTH_YN_BIT | SMP_AUTH_NO_BOND | SMP_H7_SUPPORT_BIT)
 
 /* Secure Connections, MITM, Bonding */
-#define SMP_AUTH_SC_MITM_GB     (SMP_SC_SUPPORT_BIT | SMP_AUTH_YN_BIT | SMP_AUTH_GEN_BOND)
+#define SMP_AUTH_SC_MITM_GB     (SMP_SC_SUPPORT_BIT | SMP_AUTH_YN_BIT | SMP_AUTH_GEN_BOND | SMP_H7_SUPPORT_BIT)
 
  /* All AuthReq RFU bits are set to 1 - NOTE: reserved bit in Bonding_Flags is not set */
 #define SMP_AUTH_ALL_RFU_SET    0xF8
diff --git a/stack/l2cap/l2c_api.c b/stack/l2cap/l2c_api.c
index 62012c6..d7bfb16 100644
--- a/stack/l2cap/l2c_api.c
+++ b/stack/l2cap/l2c_api.c
@@ -62,7 +62,7 @@
     tL2C_RCB    *p_rcb;
     UINT16      vpsm = psm;
 
-    L2CAP_TRACE_API ("L2CAP - L2CA_Register() called for PSM: 0x%04x", psm);
+    L2CAP_TRACE_WARNING ("L2CAP - L2CA_Register() called for PSM: 0x%04x", psm);
 
     /* Verify that the required callback info has been filled in
     **      Note:  Connection callbacks are required but not checked
@@ -131,7 +131,7 @@
     tL2C_LCB    *p_lcb;
     int         ii;
 
-    L2CAP_TRACE_API ("L2CAP - L2CA_Deregister() called for PSM: 0x%04x", psm);
+    L2CAP_TRACE_WARNING ("L2CAP - L2CA_Deregister() called for PSM: 0x%04x", psm);
 
     if ((p_rcb = l2cu_find_rcb_by_psm (psm)) != NULL)
     {
@@ -242,7 +242,7 @@
     tL2C_CCB        *p_ccb;
     tL2C_RCB        *p_rcb;
 
-    L2CAP_TRACE_API ("L2CA_ErtmConnectReq()  PSM: 0x%04x  BDA: %08x%04x  p_ertm_info: 0x%08x allowed:0x%x preferred:%d", psm,
+    L2CAP_TRACE_WARNING ("L2CA_ErtmConnectReq()  PSM: 0x%04x  BDA: %08x%04x  p_ertm_info: 0x%08x allowed:0x%x preferred:%d", psm,
                       (p_bd_addr[0]<<24)+(p_bd_addr[1]<<16)+(p_bd_addr[2]<<8)+p_bd_addr[3],
                       (p_bd_addr[4]<<8)+p_bd_addr[5], p_ertm_info,
                       (p_ertm_info) ? p_ertm_info->allowed_modes : 0,
@@ -703,7 +703,7 @@
     tL2C_LCB        *p_lcb;
     tL2C_CCB        *p_ccb;
 
-    L2CAP_TRACE_API ("L2CA_ErtmConnectRsp()  CID: 0x%04x  Result: %d  Status: %d  BDA: %08x%04x  p_ertm_info:0x%08x",
+    L2CAP_TRACE_WARNING ("L2CA_ErtmConnectRsp()  CID: 0x%04x  Result: %d  Status: %d  BDA: %08x%04x  p_ertm_info:0x%08x",
                       lcid, result, status,
                       (p_bd_addr[0]<<24)+(p_bd_addr[1]<<16)+(p_bd_addr[2]<<8)+p_bd_addr[3],
                       (p_bd_addr[4]<<8)+p_bd_addr[5], p_ertm_info);
@@ -879,7 +879,7 @@
 {
     tL2C_CCB        *p_ccb;
 
-    L2CAP_TRACE_API ("L2CA_DisconnectReq()  CID: 0x%04x", cid);
+    L2CAP_TRACE_WARNING ("L2CA_DisconnectReq()  CID: 0x%04x", cid);
 
     /* Find the channel control block. We don't know the link it is on. */
     if ((p_ccb = l2cu_find_ccb_by_cid (NULL, cid)) == NULL)
@@ -907,7 +907,7 @@
 {
     tL2C_CCB        *p_ccb;
 
-    L2CAP_TRACE_API ("L2CA_DisconnectRsp()  CID: 0x%04x", cid);
+    L2CAP_TRACE_WARNING ("L2CA_DisconnectRsp()  CID: 0x%04x", cid);
 
     /* Find the channel control block. We don't know the link it is on. */
     if ((p_ccb = l2cu_find_ccb_by_cid (NULL, cid)) == NULL)
@@ -1198,7 +1198,7 @@
 *******************************************************************************/
 UINT8 L2CA_SetDesireRole (UINT8 new_role)
 {
-    L2CAP_TRACE_API ("L2CA_SetDesireRole() new:x%x, disallow_switch:%d",
+    L2CAP_TRACE_WARNING ("L2CA_SetDesireRole() new:x%x, disallow_switch:%d",
         new_role, l2cb.disallow_switch);
 
     if (L2CAP_ROLE_CHECK_SWITCH != (L2CAP_ROLE_CHECK_SWITCH & new_role))
@@ -1313,7 +1313,7 @@
     tL2C_CCB  *p_ccb;
     BOOLEAN   on_off = !data_enabled;
 
-    L2CAP_TRACE_API ("L2CA_FlowControl(%d)  CID: 0x%04x", on_off, cid);
+    L2CAP_TRACE_WARNING ("L2CA_FlowControl(%d)  CID: 0x%04x", on_off, cid);
 
     /* Find the channel control block. We don't know the link it is on. */
     if ((p_ccb = l2cu_find_ccb_by_cid (NULL, cid)) == NULL)
@@ -2136,6 +2136,30 @@
     return l2c_data_write (cid, p_data, L2CAP_FLUSHABLE_CH_BASED);
 }
 
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+/*******************************************************************************
+**
+** Function         L2CA_GetDestChannelID
+**
+** Description      Higher layers call this function to fetch destination channel id.
+**
+** Returns          Destination Channel ID
+**
+*******************************************************************************/
+UINT16 L2CA_GetDestChannelID (UINT16 cid)
+{
+    tL2C_CCB        *p_ccb;
+    L2CAP_TRACE_API ("L2CA_GetDestChannelID: local cid: %d", cid);
+
+    /* Find the channel control block. We don't know the link it is on. */
+    p_ccb = l2cu_find_ccb_by_cid (NULL, cid);
+    L2CAP_TRACE_DEBUG("local cid: %d, dest cid: %d",
+                p_ccb->local_cid, p_ccb->remote_cid);
+
+    return p_ccb->remote_cid;
+}
+#endif
+
 /*******************************************************************************
 **
 ** Function         L2CA_SetChnlFlushability
diff --git a/stack/l2cap/l2c_ble.c b/stack/l2cap/l2c_ble.c
index 307903e..c1edce2 100644
--- a/stack/l2cap/l2c_ble.c
+++ b/stack/l2cap/l2c_ble.c
@@ -31,6 +31,7 @@
 #include "btm_int.h"
 #include "hcimsgs.h"
 #include "device/include/controller.h"
+#include "device/include/interop.h"
 #include "stack_config.h"
 #include "btif_debug_l2c.h"
 #include "log/log.h"
@@ -59,17 +60,17 @@
     /* There can be only one BLE connection request outstanding at a time */
     if (btm_ble_get_conn_st() == BLE_CONN_IDLE)
     {
-        L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - no connection pending");
+        L2CAP_TRACE_WARNING ("%s - no connection pending", __func__);
         return(FALSE);
     }
 
     if (memcmp (rem_bda, l2cb.ble_connecting_bda, BD_ADDR_LEN))
     {
-        L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - different  BDA Connecting: %08x%04x  Cancel: %08x%04x",
+        L2CAP_TRACE_WARNING ("%s - different  BDA Connecting: %08x%04x  Cancel: %08x%04x", __func__,
                               (l2cb.ble_connecting_bda[0]<<24)+(l2cb.ble_connecting_bda[1]<<16)+(l2cb.ble_connecting_bda[2]<<8)+l2cb.ble_connecting_bda[3],
                               (l2cb.ble_connecting_bda[4]<<8)+l2cb.ble_connecting_bda[5],
                               (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]);
-
+        btm_ble_dequeue_direct_conn_req(rem_bda);
         return(FALSE);
     }
 
@@ -249,6 +250,7 @@
     tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
     tACL_CONN *p_acl = btm_bda_to_acl(bda, BT_TRANSPORT_LE) ;
     tL2C_CCB *p_ccb;
+    /*BD_NAME bdname;*/
 
     if (p_lcb != NULL && p_acl != NULL && p_lcb->link_state != LST_CONNECTED)
     {
@@ -267,6 +269,13 @@
                 l2c_csm_execute (p_ccb, L2CEVT_LP_CONNECT_CFM, NULL);
         }
     }
+
+
+    /*if (!BTM_GetRemoteDeviceName(bda, bdname) || !*bdname ||
+        (!interop_match_name(INTEROP_DISABLE_LE_CONN_PREFERRED_PARAMS, (const char*) bdname)))
+    {
+        l2cble_use_preferred_conn_params(bda);
+    }*/
 }
 
 /*******************************************************************************
@@ -657,6 +666,9 @@
                 if (min_interval < BTM_BLE_CONN_INT_MIN_LIMIT)
                     min_interval = BTM_BLE_CONN_INT_MIN_LIMIT;
 
+                if (max_interval < BTM_BLE_CONN_INT_MIN_LIMIT)
+                    max_interval = BTM_BLE_CONN_INT_MIN_LIMIT;
+
                 if (min_interval < BTM_BLE_CONN_INT_MIN || min_interval > BTM_BLE_CONN_INT_MAX ||
                     max_interval < BTM_BLE_CONN_INT_MIN || max_interval > BTM_BLE_CONN_INT_MAX ||
                     latency  > BTM_BLE_CONN_LATENCY_MAX ||
@@ -903,6 +915,7 @@
     UINT8 peer_addr_type = BLE_ADDR_PUBLIC;
     UINT8 own_addr_type = BLE_ADDR_PUBLIC;
 
+    L2CAP_TRACE_WARNING ("l2cble_init_direct_conn");
     /* There can be only one BLE connection request outstanding at a time */
     if (p_dev_rec == NULL)
     {
@@ -942,40 +955,68 @@
         return FALSE;
     }
 
-    if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int      */
-                                        scan_win, /* UINT16 scan_win      */
-                                        FALSE,                   /* UINT8 white_list     */
-                                        peer_addr_type,          /* UINT8 addr_type_peer */
-                                        peer_addr,               /* BD_ADDR bda_peer     */
-                                        own_addr_type,         /* UINT8 addr_type_own  */
-        (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
-        p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),  /* UINT16 conn_int_min  */
-        (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
-        p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),  /* UINT16 conn_int_max  */
-        (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
-        p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency  */
-        (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
-        p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */
-                                        0,                       /* UINT16 min_len       */
-                                        0))                      /* UINT16 max_len       */
+#if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE))
+    if (controller_get_interface()->supports_ble_extended_advertisements())
     {
-        l2cu_release_lcb (p_lcb);
-        L2CAP_TRACE_ERROR("initate direct connection fail, no resources");
-        return (FALSE);
+        L2CAP_TRACE_WARNING ("l2cble_init_direct_conn::Calling btsnd_hcic_ble_ext_create_ll_conn");
+        if (!btsnd_hcic_ble_ext_create_ll_conn (1 /*LE 1M PHY*/, scan_int,/* UINT16 scan_int      */
+                                            scan_win, /* UINT16 scan_win      */
+                                            FALSE,                   /* UINT8 white_list     */
+                                            peer_addr_type,          /* UINT8 addr_type_peer */
+                                            peer_addr,               /* BD_ADDR bda_peer     */
+                                            own_addr_type,         /* UINT8 addr_type_own  */
+                    (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
+                    p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),  /* UINT16 conn_int_min  */
+                    (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
+                    p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),  /* UINT16 conn_int_max  */
+                    (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
+                    p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency  */
+                    (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
+                    p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */
+                                                    0,                       /* UINT16 min_len       */
+                                                    0))                      /* UINT16 max_len       */
+        {
+            l2cu_release_lcb (p_lcb);
+            L2CAP_TRACE_ERROR("initate direct connection fail, no resources");
+            return (FALSE);
+        }
     }
     else
+#endif
     {
-        p_lcb->link_state = LST_CONNECTING;
-        l2cb.is_ble_connecting = TRUE;
-        memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
-        alarm_set_on_queue(p_lcb->l2c_lcb_timer,
-                           L2CAP_BLE_LINK_CONNECT_TIMEOUT_MS,
-                           l2c_lcb_timer_timeout, p_lcb,
-                           btu_general_alarm_queue);
-        btm_ble_set_conn_st (BLE_DIR_CONN);
-
-        return (TRUE);
+        if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int      */
+                                            scan_win, /* UINT16 scan_win      */
+                                            FALSE,                   /* UINT8 white_list     */
+                                            peer_addr_type,          /* UINT8 addr_type_peer */
+                                            peer_addr,               /* BD_ADDR bda_peer     */
+                                            own_addr_type,         /* UINT8 addr_type_own  */
+            (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
+            p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),  /* UINT16 conn_int_min  */
+            (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
+            p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),  /* UINT16 conn_int_max  */
+            (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
+            p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency  */
+            (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
+            p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */
+                                            0,                       /* UINT16 min_len       */
+                                            0))                      /* UINT16 max_len       */
+        {
+            l2cu_release_lcb (p_lcb);
+            L2CAP_TRACE_ERROR("initate direct connection fail, no resources");
+            return (FALSE);
+        }
     }
+
+    p_lcb->link_state = LST_CONNECTING;
+    l2cb.is_ble_connecting = TRUE;
+    memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
+    alarm_set_on_queue(p_lcb->l2c_lcb_timer,
+                       L2CAP_BLE_LINK_CONNECT_TIMEOUT_MS,
+                       l2c_lcb_timer_timeout, p_lcb,
+                       btu_general_alarm_queue);
+    btm_ble_set_conn_st (BLE_DIR_CONN);
+
+    return (TRUE);
 }
 
 /*******************************************************************************
@@ -1488,6 +1529,33 @@
     }
 }
 
+#if (defined(LE_L2CAP_CFC_INCLUDED) && (LE_L2CAP_CFC_INCLUDED == TRUE))
+/*******************************************************************************
+**
+** Function         L2CA_LE_SetFlowControlCredits
+**
+** Description      This function sets the credits for LE incase credits did
+**                  not set during the LE connection establishment.
+**
+** Returns          TRUE if flow control set,false otherwise
+**
+*******************************************************************************/
+BOOLEAN L2CA_LE_SetFlowControlCredits (UINT16 cid, UINT16 credits)
+{
+    tL2C_CCB  *p_ccb;
+    L2CAP_TRACE_WARNING ("LE-L2CAP: %s credits: %d  CID: 0x%04x", __FUNCTION__,
+                                                                credits, cid);
+    /* Find the channel control block. We don't know the link it is on. */
+    if ((p_ccb = l2cu_find_ccb_by_cid (NULL, cid)) == NULL)
+    {
+        L2CAP_TRACE_WARNING ("LE-L2CAP: no CCB found");
+        return (FALSE);
+    }
+	l2cble_send_flow_control_credit(p_ccb, credits);
+        return (TRUE);
+}
+
+#endif //LE_L2CAP_CFC_INCLUDED
 /*******************************************************************************
 **
 ** Function         l2ble_sec_access_req
diff --git a/stack/l2cap/l2c_csm.c b/stack/l2cap/l2c_csm.c
index dedffc8..9b10de3 100644
--- a/stack/l2cap/l2c_csm.c
+++ b/stack/l2cap/l2c_csm.c
@@ -67,6 +67,11 @@
 *******************************************************************************/
 void l2c_csm_execute (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
 {
+    if (!l2cu_is_ccb_active(p_ccb)) {
+        L2CAP_TRACE_WARNING("%s This ccb is not in use, the event(%d) can't be processed", __func__, event);
+        return;
+    }
+
     switch (p_ccb->chnl_state)
     {
     case CST_CLOSED:
@@ -157,7 +162,7 @@
 #if (BT_TRACE_VERBOSE == TRUE)
     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: CLOSED  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
 #else
-    L2CAP_TRACE_EVENT ("L2CAP - st: CLOSED evt: %d", event);
+    L2CAP_TRACE_WARNING ("L2CAP - st: CLOSED evt: %d", event);
 #endif
 
     switch (event)
@@ -333,7 +338,7 @@
 #if (BT_TRACE_VERBOSE == TRUE)
     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: ORIG_W4_SEC_COMP  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
 #else
-    L2CAP_TRACE_EVENT ("L2CAP - st: ORIG_W4_SEC_COMP evt: %d", event);
+    L2CAP_TRACE_WARNING ("L2CAP - st: ORIG_W4_SEC_COMP evt: %d", event);
 #endif
 
 #if (L2CAP_UCD_INCLUDED == TRUE)
@@ -447,7 +452,7 @@
 #if (BT_TRACE_VERBOSE == TRUE)
     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: TERM_W4_SEC_COMP  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
 #else
-    L2CAP_TRACE_EVENT ("L2CAP - st: TERM_W4_SEC_COMP evt: %d", event);
+    L2CAP_TRACE_WARNING ("L2CAP - st: TERM_W4_SEC_COMP evt: %d", event);
 #endif
 
 #if (L2CAP_UCD_INCLUDED == TRUE)
@@ -475,7 +480,7 @@
         p_ccb->chnl_state = CST_W4_L2CA_CONNECT_RSP;
 
         /* Wait for the info resp in next state before sending connect ind (if needed) */
-        if (!p_ccb->p_lcb->w4_info_rsp)
+        if ((!p_ccb->p_lcb->w4_info_rsp)||(BT_PSM_SDP == p_ccb->p_rcb->psm))
         {
             /* Don't need to get info from peer or already retrieved so continue */
             alarm_set_on_queue(p_ccb->l2c_ccb_timer,
@@ -573,13 +578,14 @@
 {
     tL2C_CONN_INFO          *p_ci = (tL2C_CONN_INFO *)p_data;
     tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
+    tL2CA_DISCONNECT_CFM_CB *disconnect_cfm = p_ccb->p_rcb->api.pL2CA_DisconnectCfm_Cb;
     tL2CA_CONNECT_CFM_CB    *connect_cfm = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb;
     UINT16                  local_cid = p_ccb->local_cid;
 
 #if (BT_TRACE_VERBOSE == TRUE)
     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: W4_L2CAP_CON_RSP  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
 #else
-    L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CAP_CON_RSP evt: %d", event);
+    L2CAP_TRACE_WARNING ("L2CAP - st: W4_L2CAP_CON_RSP evt: %d", event);
 #endif
 
     switch (event)
@@ -655,7 +661,14 @@
                                btu_general_alarm_queue);
         }
         else
+        {
             l2cu_release_ccb (p_ccb);
+            if(disconnect_cfm)
+            {
+                L2CAP_TRACE_API ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
+                (*disconnect_cfm)(local_cid, L2CAP_CONN_NO_LINK);
+            }
+        }
         break;
 
     case L2CEVT_L2CA_DATA_WRITE:                    /* Upper layer data to send */
@@ -708,7 +721,7 @@
 #if (BT_TRACE_VERBOSE == TRUE)
     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: W4_L2CA_CON_RSP  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
 #else
-    L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CA_CON_RSP evt: %d", event);
+    L2CAP_TRACE_WARNING ("L2CAP - st: W4_L2CA_CON_RSP evt: %d", event);
 #endif
 
     switch (event)
@@ -827,7 +840,7 @@
 #if (BT_TRACE_VERBOSE == TRUE)
     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: CONFIG  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
 #else
-    L2CAP_TRACE_EVENT ("L2CAP - st: CONFIG evt: %d", event);
+    L2CAP_TRACE_WARNING ("L2CAP - st: CONFIG evt: %d", event);
 #endif
 
     switch (event)
@@ -912,8 +925,8 @@
                 }
             }
         }
-
-        L2CAP_TRACE_API ("L2CAP - Calling Config_Rsp_Cb(), CID: 0x%04x", p_ccb->local_cid);
+        L2CAP_TRACE_WARNING ("L2CAP-peer_Config_Rsp,Local CID: 0x%04x,Remote CID: 0x%04x,PSM: %d,peer MTU present: %d,peer MTU: %d",
+                               p_ccb->local_cid,p_ccb->remote_cid,p_ccb->p_rcb->psm ,p_ccb->peer_cfg.mtu_present,p_ccb->peer_cfg.mtu);
         (*p_ccb->p_rcb->api.pL2CA_ConfigCfm_Cb)(p_ccb->local_cid, p_cfg);
         break;
 
@@ -1000,6 +1013,8 @@
         {
             l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
         }
+        L2CAP_TRACE_WARNING ("L2CAP-Upper layer Config_Rsp,Local CID: 0x%04x,Remote CID: 0x%04x,PSM: %d,our MTU present:%d,our MTU:%d",
+                              p_ccb->local_cid,p_ccb->remote_cid, p_ccb->p_rcb->psm, p_ccb->our_cfg.mtu_present,p_ccb->our_cfg.mtu);
         break;
 
     case L2CEVT_L2CA_CONFIG_RSP_NEG:               /* Upper layer config reject */
@@ -1117,7 +1132,7 @@
         tempstate = p_ccb->chnl_state;
         tempcfgdone = p_ccb->config_done;
         p_ccb->chnl_state = CST_CONFIG;
-        p_ccb->config_done &= ~CFG_DONE_MASK;
+        p_ccb->config_done &= ~IB_CFG_DONE;
 
         alarm_set_on_queue(p_ccb->l2c_ccb_timer,
                            L2CAP_CHNL_CFG_TIMEOUT_MS,
@@ -1267,7 +1282,7 @@
 #if (BT_TRACE_VERBOSE == TRUE)
     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: W4_L2CAP_DISC_RSP  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
 #else
-    L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CAP_DISC_RSP evt: %d", event);
+    L2CAP_TRACE_WARNING ("L2CAP - st: W4_L2CAP_DISC_RSP evt: %d", event);
 #endif
 
     switch (event)
@@ -1332,7 +1347,7 @@
 #if (BT_TRACE_VERBOSE == TRUE)
     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: W4_L2CA_DISC_RSP  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
 #else
-    L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CA_DISC_RSP evt: %d", event);
+    L2CAP_TRACE_WARNING ("L2CAP - st: W4_L2CA_DISC_RSP evt: %d", event);
 #endif
 
     switch (event)
diff --git a/stack/l2cap/l2c_fcr.c b/stack/l2cap/l2c_fcr.c
index 4c0fb41..e9d373d 100644
--- a/stack/l2cap/l2c_fcr.c
+++ b/stack/l2cap/l2c_fcr.c
@@ -198,6 +198,37 @@
 
 /*******************************************************************************
 **
+** Function         l2c_fcr_restart_timer
+**
+** Description      This function starts the (monitor or retransmission) timer.
+**
+** Returns          -
+**
+*******************************************************************************/
+void l2c_fcr_restart_timer (tL2C_CCB *p_ccb)
+{
+    assert(p_ccb != NULL);
+    UINT32  tout;
+
+    /* The timers which are in milliseconds */
+    if (p_ccb->fcrb.wait_ack)
+    {
+        tout = (UINT32)p_ccb->our_cfg.fcr.mon_tout;
+    }
+    else
+    {
+        tout = (UINT32)p_ccb->our_cfg.fcr.rtrans_tout;
+    }
+
+    /* restart the mentioned timer */
+    alarm_set_on_queue(p_ccb->fcrb.mon_retrans_timer, tout,
+                       l2c_ccb_timer_timeout, p_ccb,
+                       btu_general_alarm_queue);
+}
+
+
+/*******************************************************************************
+**
 ** Function         l2c_fcr_stop_timer
 **
 ** Description      This function stops the (monitor or transmission) timer.
@@ -1048,6 +1079,10 @@
         for (xx = 0; xx < num_bufs_acked; xx++)
         {
             BT_HDR *p_tmp = (BT_HDR *)fixed_queue_try_dequeue(p_fcrb->waiting_for_ack_q);
+            if (p_tmp == NULL) {
+                L2CAP_TRACE_WARNING ("%s: Unable to dequeue", __func__);
+                return (FALSE);
+            }
             ls = p_tmp->layer_specific & L2CAP_FCR_SAR_BITS;
 
             if ( (ls == L2CAP_FCR_UNSEG_SDU) || (ls == L2CAP_FCR_END_SDU) )
@@ -1057,8 +1092,6 @@
         }
 
         /* If we are still in a wait_ack state, do not mess with the timer */
-        if (!p_ccb->fcrb.wait_ack)
-            l2c_fcr_stop_timer (p_ccb);
 
         /* Check if we need to call the "packet_sent" callback */
         if ( (p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_TxComplete_Cb) && (full_sdus_xmitted) )
@@ -1074,8 +1107,15 @@
     }
 
     /* If anything still waiting for ack, restart the timer if it was stopped */
-    if (!fixed_queue_is_empty(p_fcrb->waiting_for_ack_q))
-        l2c_fcr_start_timer(p_ccb);
+    if(!p_ccb->fcrb.wait_ack) {
+        if (!fixed_queue_is_empty(p_fcrb->waiting_for_ack_q)) {
+//            l2c_fcr_start_timer(p_ccb);
+            l2c_fcr_restart_timer (p_ccb);
+        }
+        else
+            l2c_fcr_stop_timer (p_ccb);
+    }
+
     return (TRUE);
 }
 
@@ -1230,8 +1270,12 @@
             if (p_fcrb->srej_sent)
             {
                 /* If SREJ sent, save the frame for later processing as long as it is in sequence */
-                next_srej = (((BT_HDR *)fixed_queue_try_peek_last(p_fcrb->srej_rcv_hold_q))->layer_specific + 1) & L2CAP_FCR_SEQ_MODULO;
-
+                void * frame_msg = fixed_queue_try_peek_last(p_fcrb->srej_rcv_hold_q);
+                if (frame_msg == NULL) {
+                    L2CAP_TRACE_WARNING ("%s: Unable to process frame", __func__);
+                    return;
+                }
+                next_srej = (((BT_HDR *)frame_msg)->layer_specific + 1) & L2CAP_FCR_SEQ_MODULO;
                 if ( (tx_seq == next_srej) && (fixed_queue_length(p_fcrb->srej_rcv_hold_q) < p_ccb->our_cfg.fcr.tx_win_sz) )
                 {
                     /* If user gave us a pool for held rx buffers, use that */
@@ -1731,6 +1775,10 @@
     }
 
     p_buf = (BT_HDR *)fixed_queue_try_peek_first(p_ccb->xmit_hold_q);
+    if (p_buf == NULL) {
+        L2CAP_TRACE_ERROR ("%s: L2CAP - fixed_queue_try_peek_first returned queue as empty", __func__);
+        return NULL;
+    }
 
     /* If there is more data than the MPS, it requires segmentation */
     if (p_buf->len > max_pdu)
@@ -1767,8 +1815,12 @@
     }
     else    /* Use the original buffer if no segmentation, or the last segment */
     {
-        p_xmit = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
-
+        void *seg_msg = fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
+        if (seg_msg == NULL) {
+            L2CAP_TRACE_WARNING ("%s: Unable to process frame", __func__);
+            return (NULL);
+        }
+        p_xmit = (BT_HDR *)seg_msg;
         if (p_xmit->event != 0)
             last_seg = TRUE;
 
@@ -1882,6 +1934,10 @@
     UINT16      max_pdu = p_ccb->peer_conn_cfg.mps;
 
     p_buf = (BT_HDR *)fixed_queue_try_peek_first(p_ccb->xmit_hold_q);
+    if (p_buf == NULL) {
+        L2CAP_TRACE_ERROR ("%s: L2CAP - fixed_queue_try_peek_first returned queue as empty", __func__);
+        return (NULL);
+    }
 
     /* We are using the "event" field to tell is if we already started segmentation */
     if (p_buf->event == 0)
diff --git a/stack/l2cap/l2c_int.h b/stack/l2cap/l2c_int.h
index 8af47d7..bbf2409 100644
--- a/stack/l2cap/l2c_int.h
+++ b/stack/l2cap/l2c_int.h
@@ -250,7 +250,7 @@
 
 
 #ifndef L2CAP_CBB_DEFAULT_DATA_RATE_BUFF_QUOTA
-#define L2CAP_CBB_DEFAULT_DATA_RATE_BUFF_QUOTA 100
+#define L2CAP_CBB_DEFAULT_DATA_RATE_BUFF_QUOTA 10
 #endif
 
 typedef void (tL2CAP_SEC_CBACK) (BD_ADDR bd_addr, tBT_TRANSPORT trasnport,
@@ -640,6 +640,7 @@
 extern BOOLEAN l2cu_initialize_fixed_ccb (tL2C_LCB *p_lcb, UINT16 fixed_cid, tL2CAP_FCR_OPTS *p_fcr);
 extern void    l2cu_no_dynamic_ccbs (tL2C_LCB *p_lcb);
 extern void    l2cu_process_fixed_chnl_resp (tL2C_LCB *p_lcb);
+extern BOOLEAN l2cu_is_ccb_active (tL2C_CCB *p_ccb);
 
 /* Functions provided by l2c_ucd.c
 ************************************
diff --git a/stack/l2cap/l2c_link.c b/stack/l2cap/l2c_link.c
index 2fefd13..dcf1362 100644
--- a/stack/l2cap/l2c_link.c
+++ b/stack/l2cap/l2c_link.c
@@ -41,12 +41,13 @@
 #include "btm_api.h"
 #include "btm_int.h"
 #include "btcore/include/bdaddr.h"
-
+#include "device/include/interop_config.h"
 
 extern fixed_queue_t *btu_general_alarm_queue;
 
 static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf);
 
+#define HI_PRI_LINK_QUOTA 2 //Mininum ACL buffer quota for high priority link
 /*******************************************************************************
 **
 ** Function         l2c_link_hci_conn_req
@@ -63,6 +64,7 @@
     tL2C_LCB        *p_lcb_cur;
     int             xx;
     BOOLEAN         no_links;
+    bt_bdaddr_t     remote_bdaddr;
 
     /* See if we have a link control block for the remote device */
     p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr, BT_TRANSPORT_BR_EDR);
@@ -75,6 +77,7 @@
         {
             btsnd_hcic_reject_conn (bd_addr, HCI_ERR_HOST_REJECT_RESOURCES);
             L2CAP_TRACE_ERROR ("L2CAP failed to allocate LCB");
+            GENERATE_VENDOR_LOGS();
             return FALSE;
         }
 
@@ -101,7 +104,11 @@
             else
                 p_lcb->link_role = l2cu_get_conn_role(p_lcb);
         }
-
+        bdcpy(remote_bdaddr.address, bd_addr);
+        if ((p_lcb->link_role == BTM_ROLE_MASTER)&&(interop_database_match_addr(INTEROP_DISABLE_ROLE_SWITCH, (bt_bdaddr_t *)&remote_bdaddr))) {
+            p_lcb->link_role = BTM_ROLE_SLAVE;
+            L2CAP_TRACE_WARNING ("l2c_link_hci_conn_req:set link_role= %d",p_lcb->link_role);
+        }
 
         /* Tell the other side we accept the connection */
         btsnd_hcic_accept_conn (bd_addr, p_lcb->link_role);
@@ -175,6 +182,13 @@
     if (!p_lcb)
     {
         L2CAP_TRACE_WARNING ("L2CAP got conn_comp for unknown BD_ADDR");
+
+        /* Connection complete received when no link control block is present for this address
+         * However ACL entry is already created
+         * Removing connection entry at ACL and sending disconnect because l2c and acl are out of sync */
+        btm_remove_acl(p_bda, BT_TRANSPORT_BR_EDR);
+        btm_acl_removed(p_bda, BT_TRANSPORT_BR_EDR);
+
         return (FALSE);
     }
 
@@ -276,6 +290,7 @@
             {
                 /* we are in collision situation, wait for connecttion request from controller */
                 p_lcb->link_state = LST_CONNECTING;
+                GENERATE_VENDOR_LOGS();
             }
             else
             {
@@ -487,6 +502,28 @@
           }
 #endif
         }
+            if (p_lcb->transport == BT_TRANSPORT_BR_EDR)
+            {
+                if (p_lcb->sent_not_acked > 0)
+                {
+                    l2cb.controller_xmit_window += p_lcb->sent_not_acked;
+                    if (l2cb.controller_xmit_window > l2cb.num_lm_acl_bufs)
+                    {
+                        l2cb.controller_xmit_window = l2cb.num_lm_acl_bufs;
+                    }
+                    p_lcb->sent_not_acked = 0;
+                }
+                p_lcb->partial_segment_being_sent = FALSE;
+
+                /* Stop the link connect timer if sent */
+                if (p_lcb->w4_info_rsp)
+                {
+                    alarm_cancel(p_lcb->l2c_lcb_timer);
+                    p_lcb->w4_info_rsp = FALSE;
+                }
+
+                btm_acl_removed(p_lcb->remote_bd_addr, BT_TRANSPORT_BR_EDR);
+            }
             if (l2cu_create_conn(p_lcb, transport))
                 lcb_is_free = FALSE; /* still using this lcb */
         }
@@ -587,6 +624,9 @@
 #endif
         /* Release the LCB */
         l2cu_release_lcb (p_lcb);
+
+        /*Generate logs for link timeout while connecting/disconnecting*/
+        GENERATE_VENDOR_LOGS();
     }
 
     /* If link is connected, check for inactivity timeout */
@@ -652,6 +692,9 @@
                 l2cu_process_fixed_disc_cback(p_lcb);
                 p_lcb->link_state = LST_DISCONNECTING;
                 timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS;
+
+                /*Link timeout must not occur while bonding*/
+                GENERATE_VENDOR_LOGS();
             }
             else
             {
@@ -775,6 +818,14 @@
     while ( (num_hipri_links * high_pri_link_quota + low_quota) > controller_xmit_quota )
         high_pri_link_quota--;
 
+    /*Adjust high pri link with min 3 buffers*/
+    if(num_hipri_links > 0)
+    {
+      if(high_pri_link_quota < HI_PRI_LINK_QUOTA)
+      {
+        high_pri_link_quota  = HI_PRI_LINK_QUOTA;
+      }
+    }
     /* Work out the xmit quota and buffer quota high and low priorities */
     hi_quota  = num_hipri_links * high_pri_link_quota;
     low_quota = (hi_quota < controller_xmit_quota) ? controller_xmit_quota - hi_quota : 1;
diff --git a/stack/l2cap/l2c_main.c b/stack/l2cap/l2c_main.c
index 92e92ca..c9344f8 100644
--- a/stack/l2cap/l2c_main.c
+++ b/stack/l2cap/l2c_main.c
@@ -114,7 +114,7 @@
                 }
 
                 return;
-            } else {
+            } else if (handle != 0xedc) {    /* Handle 0xedc used for SOC Logging */
                 L2CAP_TRACE_ERROR ("L2CAP - rcvd ACL for unknown handle:%d ls:%d cid:%d"
                         " opcode:%d cur count:%d", handle, p_msg->layer_specific, rcv_cid,
                         cmd_code, list_length(l2cb.rcv_pending_q));
@@ -316,6 +316,12 @@
         STREAM_TO_UINT8  (id, p);
         STREAM_TO_UINT16 (cmd_len, p);
 
+        if(cmd_len > BT_SMALL_BUFFER_SIZE)
+        {
+             L2CAP_TRACE_WARNING ("L2CAP - Invalid MTU Size");
+             l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_MTU_EXCEEDED, id, 0, 0);
+             return;
+        }
         /* Check command length does not exceed packet length */
         if ((p_next_cmd = p + cmd_len) > p_pkt_end)
         {
@@ -475,7 +481,7 @@
             p_cfg_start = p;
 
             cfg_info.flush_to_present = cfg_info.mtu_present = cfg_info.qos_present =
-                cfg_info.fcr_present = cfg_info.fcs_present = FALSE;
+            cfg_info.fcr_present = cfg_info.fcs_present = FALSE;
 
             while (p < p_cfg_end)
             {
@@ -780,7 +786,7 @@
             break;
 
         case L2CAP_CMD_ECHO_REQ:
-            l2cu_send_peer_echo_rsp (p_lcb, id, NULL, 0);
+            l2cu_send_peer_echo_rsp (p_lcb, id, p, cmd_len);
             break;
 
         case L2CAP_CMD_ECHO_RSP:
diff --git a/stack/l2cap/l2c_utils.c b/stack/l2cap/l2c_utils.c
index 72bd52e..6e51747 100644
--- a/stack/l2cap/l2c_utils.c
+++ b/stack/l2cap/l2c_utils.c
@@ -1677,16 +1677,22 @@
 *******************************************************************************/
 void l2cu_release_ccb (tL2C_CCB *p_ccb)
 {
-    tL2C_LCB    *p_lcb = p_ccb->p_lcb;
-    tL2C_RCB    *p_rcb = p_ccb->p_rcb;
+    tL2C_LCB    *p_lcb = NULL;
+    tL2C_RCB    *p_rcb = NULL;
 
     L2CAP_TRACE_DEBUG ("l2cu_release_ccb: cid 0x%04x  in_use: %u", p_ccb->local_cid, p_ccb->in_use);
 
     /* If already released, could be race condition */
-    if (!p_ccb->in_use)
+    if (!p_ccb || !p_ccb->in_use)
         return;
+    p_lcb = p_ccb->p_lcb;
+    p_rcb = p_ccb->p_rcb;
 
+#if (defined(LE_L2CAP_CFC_INCLUDED) && (LE_L2CAP_CFC_INCLUDED == TRUE))
+    if (p_rcb && p_lcb && (p_rcb->psm != p_rcb->real_psm))
+#else
     if (p_rcb && (p_rcb->psm != p_rcb->real_psm))
+#endif
     {
         btm_sec_clr_service_by_psm(p_rcb->psm);
     }
@@ -1698,7 +1704,8 @@
         p_ccb->should_free_rcb = false;
     }
 
-    btm_sec_clr_temp_auth_service (p_lcb->remote_bd_addr);
+    if(p_lcb)
+       btm_sec_clr_temp_auth_service (p_lcb->remote_bd_addr);
 
     /* Free the timer */
     alarm_free(p_ccb->l2c_ccb_timer);
@@ -2568,6 +2575,12 @@
         return (FALSE);
     }
 
+    if (p_lcb->acl_priority != priority)
+    {
+        p_lcb->acl_priority = priority;
+        l2c_link_adjust_allocation();
+    }
+
     if (BTM_IS_BRCM_CONTROLLER())
     {
         /* Called from above L2CAP through API; send VSC if changed */
@@ -2860,13 +2873,17 @@
         }
     }
 
+    if (timeout_ms == (1000) * (0xFFFF))
+        start_timeout = false;
+
     if (start_timeout) {
-        L2CAP_TRACE_DEBUG("%s starting IDLE timeout: %d ms", __func__,
+        L2CAP_TRACE_DEBUG("%s starting IDLE timeout: %llu ms", __func__,
                           timeout_ms);
         alarm_set_on_queue(p_lcb->l2c_lcb_timer, timeout_ms,
                            l2c_lcb_timer_timeout, p_lcb,
                            btu_general_alarm_queue);
     } else {
+        L2CAP_TRACE_DEBUG("%s, alarm cancel", __func__);
         alarm_cancel(p_lcb->l2c_lcb_timer);
     }
 }
@@ -3790,7 +3807,7 @@
                 p_ccb->cong_sent = TRUE;
                 if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)
                 {
-                    L2CAP_TRACE_DEBUG ("L2CAP - Calling CongestionStatus_Cb (TRUE),CID:0x%04x,XmitQ:%u,Quota:%u",
+                    L2CAP_TRACE_WARNING ("L2CAP - Calling CongestionStatus_Cb (TRUE),CID:0x%04x,XmitQ:%u,Quota:%u",
                         p_ccb->local_cid, q_count, p_ccb->buff_quota);
 
                     (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, TRUE);
@@ -3828,3 +3845,17 @@
     }
 }
 
+/*******************************************************************************
+**
+** Function         l2cu_is_ccb_active
+**
+** Description      Check if Channel Control Block is in use or released
+**
+** Returns          BOOLEAN - TRUE if Channel Control Block is in use
+**                            FALSE if p_ccb is null or is released.
+**
+*******************************************************************************/
+BOOLEAN l2cu_is_ccb_active (tL2C_CCB *p_ccb)
+{
+    return (p_ccb && p_ccb->in_use);
+}
diff --git a/stack/l2cap/l2cap_client.c b/stack/l2cap/l2cap_client.c
index cd7edfe..e96d3d3 100644
--- a/stack/l2cap/l2cap_client.c
+++ b/stack/l2cap/l2cap_client.c
@@ -98,6 +98,10 @@
   }
 
   l2cap_client_t *ret = (l2cap_client_t *)osi_calloc(sizeof(l2cap_client_t));
+  if (ret == NULL) {
+    LOG_ERROR(LOG_TAG, "%s unable to allocate space for L2CAP client.", __func__);
+    return NULL;
+  }
 
   ret->callbacks = *callbacks;
   ret->context = context;
diff --git a/stack/mcap/mca_cact.c b/stack/mcap/mca_cact.c
index 8a75283..4b42f0f 100644
--- a/stack/mcap/mca_cact.c
+++ b/stack/mcap/mca_cact.c
@@ -31,7 +31,7 @@
 #include "mca_api.h"
 #include "mca_defs.h"
 #include "mca_int.h"
-
+#include <unistd.h>
 
 #include  "btu.h"
 
@@ -110,8 +110,11 @@
         p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx);
         /* the Abort API does not have the associated mdl_id.
          * Get the mdl_id in dcb to compose the request */
-        p_msg->mdl_id = p_dcb->mdl_id;
-        mca_dcb_event(p_dcb, MCA_DCB_API_CLOSE_EVT, NULL);
+        if(p_dcb)
+        {
+            p_msg->mdl_id = p_dcb->mdl_id;
+            mca_dcb_event(p_dcb, MCA_DCB_API_CLOSE_EVT, NULL);
+        }
         osi_free_and_reset((void **)&p_ccb->p_tx_req);
         p_ccb->status = MCA_CCB_STAT_NORM;
         is_abort = TRUE;
@@ -402,6 +405,9 @@
                 case MCA_OP_MDL_DELETE_REQ:
                     /* delete the associated mdl */
                     mca_dcb_close_by_mdl_id(p_ccb, evt_data.hdr.mdl_id);
+#if (defined(MCA_DELAY_DELETE_MDL_RSP) && MCA_DELAY_DELETE_MDL_RSP == TRUE)
+                    sleep(5);
+#endif
                     send_rsp = TRUE;
                     break;
                 }
@@ -503,7 +509,7 @@
             if (chk_mdl)
             {
                 p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx);
-                if (evt_data.rsp.rsp_code == MCA_RSP_SUCCESS)
+                if (p_dcb && evt_data.rsp.rsp_code == MCA_RSP_SUCCESS)
                 {
                     if (evt_data.hdr.mdl_id != p_dcb->mdl_id)
                     {
diff --git a/stack/mcap/mca_csm.c b/stack/mcap/mca_csm.c
index 1ded765..f643e92 100644
--- a/stack/mcap/mca_csm.c
+++ b/stack/mcap/mca_csm.c
@@ -198,7 +198,7 @@
     p_ccb->state = state_table[event][MCA_CCB_NEXT_STATE];
 
     /* execute action functions */
-    if ((action = state_table[event][MCA_CCB_ACT_COL]) != MCA_CCB_IGNORE)
+    if ((action = state_table[event][MCA_CCB_ACT_COL]) < MCA_CCB_IGNORE)
     {
         (*mca_ccb_action[action])(p_ccb, p_data);
     }
@@ -366,10 +366,18 @@
 {
     BOOLEAN uses = FALSE;
     tMCA_DCB *p_dcb;
-    int       i;
+    unsigned int i;
 
     i = mca_ccb_to_hdl(p_ccb)-1;
-    p_dcb = &mca_cb.dcb[i*MCA_NUM_MDLS];
+    if (i*MCA_NUM_MDLS < MCA_NUM_DCBS)
+    {
+        p_dcb = &mca_cb.dcb[i*MCA_NUM_MDLS];
+    }
+    else
+    {
+        MCA_TRACE_WARNING("dcb index out of range");
+        return uses;
+    }
     for (i=0; i<MCA_NUM_MDLS; i++, p_dcb++)
     {
         if (p_dcb->state != MCA_DCB_NULL_ST && p_dcb->mdl_id == mdl_id)
diff --git a/stack/mcap/mca_dsm.c b/stack/mcap/mca_dsm.c
index c76e020..e122d43 100644
--- a/stack/mcap/mca_dsm.c
+++ b/stack/mcap/mca_dsm.c
@@ -154,7 +154,7 @@
     p_dcb->state = state_table[event][MCA_DCB_NEXT_STATE];
 
     /* execute action functions */
-    if ((action = state_table[event][MCA_DCB_ACT_COL]) != MCA_DCB_IGNORE)
+    if ((action = state_table[event][MCA_DCB_ACT_COL]) < MCA_DCB_IGNORE)
     {
         (*mca_dcb_action[action])(p_dcb, p_data);
     }
@@ -175,13 +175,21 @@
     tMCA_DCB *p_dcb = NULL, *p_dcb_tmp;
     tMCA_RCB *p_rcb = p_ccb->p_rcb;
     tMCA_CS  *p_cs;
-    int       i, max;
+    unsigned int  i, max;
 
     if (dep < MCA_NUM_DEPS)
     {
         p_cs = &p_rcb->dep[dep];
         i = mca_ccb_to_hdl(p_ccb)-1;
-        p_dcb_tmp = &mca_cb.dcb[i*MCA_NUM_MDLS];
+        if( i*MCA_NUM_MDLS < MCA_NUM_DCBS)
+        {
+            p_dcb_tmp = &mca_cb.dcb[i*MCA_NUM_MDLS];
+        }
+        else
+        {
+            MCA_TRACE_WARNING("dcb index out of range");
+            return NULL;
+        }
         /* make sure p_cs->max_mdl is smaller than MCA_NUM_MDLS at MCA_CreateDep */
         max = p_cs->max_mdl;
         for (i=0; i<max; i++, p_dcb_tmp++)
@@ -215,7 +223,7 @@
     tMCA_DCB *p_dcb;
     tMCA_RCB *p_rcb = p_ccb->p_rcb;
     tMCA_CS  *p_cs;
-    int       i, max;
+    unsigned int i, max;
     UINT8   count = 0;
     UINT8   left;
 
@@ -223,7 +231,15 @@
     {
         p_cs = &p_rcb->dep[dep];
         i = mca_ccb_to_hdl(p_ccb)-1;
-        p_dcb = &mca_cb.dcb[i * MCA_NUM_MDLS];
+        if( i*MCA_NUM_MDLS < MCA_NUM_DCBS)
+        {
+            p_dcb = &mca_cb.dcb[i * MCA_NUM_MDLS];
+        }
+        else
+        {
+            MCA_TRACE_WARNING("dcb index out of range");
+            return 0;
+        }
         /* make sure p_cs->max_mdl is smaller than MCA_NUM_MDLS at MCA_CreateDep */
         max = p_cs->max_mdl;
         for (i=0; i<max; i++, p_dcb++)
@@ -327,7 +343,15 @@
 
     MCA_TRACE_DEBUG("mca_dcb_close_by_mdl_id mdl_id=%d", mdl_id);
     i = mca_ccb_to_hdl(p_ccb)-1;
-    p_dcb = &mca_cb.dcb[i*MCA_NUM_MDLS];
+    if( i*MCA_NUM_MDLS < MCA_NUM_DCBS)
+    {
+        p_dcb = &mca_cb.dcb[i * MCA_NUM_MDLS];
+    }
+    else
+    {
+        MCA_TRACE_WARNING("dcb index out of range");
+        return;
+    }
     for (i=0; i<MCA_NUM_MDLS; i++, p_dcb++)
     {
         if (p_dcb->state)
diff --git a/stack/mcap/mca_l2c.c b/stack/mcap/mca_l2c.c
index 62caf78..9456d3d 100644
--- a/stack/mcap/mca_l2c.c
+++ b/stack/mcap/mca_l2c.c
@@ -204,7 +204,7 @@
 
         /* if result ok, proceed with connection and send L2CAP
            config req */
-        if (result == L2CAP_CONN_OK)
+        if (result == L2CAP_CONN_OK && p_tbl)
         {
             /* set channel state */
             p_tbl->state = MCA_TC_ST_CFG;
diff --git a/stack/mcap/mca_main.c b/stack/mcap/mca_main.c
index d1591b3..14ca09a 100644
--- a/stack/mcap/mca_main.c
+++ b/stack/mcap/mca_main.c
@@ -255,7 +255,7 @@
 void mca_set_cfg_by_tbl(tL2CAP_CFG_INFO *p_cfg, tMCA_TC_TBL *p_tbl)
 {
     tMCA_DCB   *p_dcb;
-    const tL2CAP_FCR_OPTS *p_opt;
+    const tL2CAP_FCR_OPTS *p_opt = NULL;
     tMCA_FCS_OPT    fcs = MCA_FCS_NONE;
 
     if (p_tbl->tcid == MCA_CTRL_TCID)
@@ -265,7 +265,7 @@
     else
     {
         p_dcb = mca_dcb_by_hdl(p_tbl->cb_idx);
-        if (p_dcb)
+        if (p_dcb != NULL)
         {
             p_opt = &p_dcb->p_chnl_cfg->fcr_opt;
             fcs   = p_dcb->p_chnl_cfg->fcs;
@@ -275,7 +275,8 @@
     p_cfg->mtu_present = TRUE;
     p_cfg->mtu = p_tbl->my_mtu;
     p_cfg->fcr_present = TRUE;
-    memcpy(&p_cfg->fcr, p_opt, sizeof (tL2CAP_FCR_OPTS));
+    if (p_opt != NULL)
+        memcpy(&p_cfg->fcr, p_opt, sizeof (tL2CAP_FCR_OPTS));
     if (fcs & MCA_FCS_PRESNT_MASK)
     {
         p_cfg->fcs_present = TRUE;
@@ -323,7 +324,10 @@
     if (p_tbl->tcid == MCA_CTRL_TCID)
     {
         p_ccb = mca_ccb_by_hdl((tMCA_CL)p_tbl->cb_idx);
-        mca_ccb_event(p_ccb, MCA_CCB_LL_CLOSE_EVT, (tMCA_CCB_EVT *)&close);
+        if(p_ccb != NULL)
+        {
+            mca_ccb_event(p_ccb, MCA_CCB_LL_CLOSE_EVT, (tMCA_CCB_EVT *)&close);
+        }
     }
     /* notify dcb that channel close */
     else
@@ -372,8 +376,10 @@
     if (p_tbl->tcid == MCA_CTRL_TCID)
     {
         p_ccb = mca_ccb_by_hdl((tMCA_CL)p_tbl->cb_idx);
-
-        mca_ccb_event(p_ccb, MCA_CCB_LL_OPEN_EVT, (tMCA_CCB_EVT *)&open);
+        if(p_ccb != NULL)
+        {
+            mca_ccb_event(p_ccb, MCA_CCB_LL_OPEN_EVT, (tMCA_CCB_EVT *)&open);
+        }
     }
     /* must be data channel, notify dcb that channel open */
     else
@@ -415,7 +421,10 @@
     if (p_tbl->tcid == MCA_CTRL_TCID)
     {
         p_ccb = mca_ccb_by_hdl((tMCA_CL)p_tbl->cb_idx);
-        mca_ccb_event(p_ccb, MCA_CCB_LL_CONG_EVT, (tMCA_CCB_EVT *) &is_congested);
+        if (p_ccb != NULL)
+        {
+            mca_ccb_event(p_ccb, MCA_CCB_LL_CONG_EVT, (tMCA_CCB_EVT *) &is_congested);
+        }
     }
     /* notify dcb that channel open */
     else
diff --git a/stack/pan/pan_api.c b/stack/pan/pan_api.c
index a20ed57..d56bf1f 100644
--- a/stack/pan/pan_api.c
+++ b/stack/pan/pan_api.c
@@ -407,6 +407,7 @@
     result = BNEP_Connect (rem_bda, &src_uuid, &dst_uuid, &(pcb->handle));
     if (result != BNEP_SUCCESS)
     {
+        pan_cb.num_conns--;
         pan_release_pcb (pcb);
         return result;
     }
diff --git a/stack/rfcomm/port_api.c b/stack/rfcomm/port_api.c
index 13457f9..0c90866 100644
--- a/stack/rfcomm/port_api.c
+++ b/stack/rfcomm/port_api.c
@@ -527,6 +527,51 @@
 
 /*******************************************************************************
 **
+** Function         PORT_GetRemoteMtu
+**
+** Description      This function feteches remote mtu from port
+**
+** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
+**
+** Returns:         UINT16     - Maximum rfcomm frame size that can be
+**                               transmitted to the peer
+**
+*******************************************************************************/
+UINT16 PORT_GetRemoteMtu (UINT16 handle)
+{
+    tPORT      *p_port;
+
+    RFCOMM_TRACE_API ("PORT_GetRemoteMtu() handle:%d", handle);
+
+    /* Check if handle is valid to avoid crashing */
+    if ((handle == 0) || (handle > MAX_RFC_PORTS))
+    {
+        return (0);
+    }
+
+    p_port = &rfc_cb.port.port[handle - 1];
+
+    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
+    {
+        RFCOMM_TRACE_ERROR ("PORT_GetRemoteMtu() p_port->in_use = %d, p_port->state = %d",
+               p_port->in_use, p_port->state);
+        return (0);
+    }
+
+    if (!p_port->rfc.p_mcb
+     || !p_port->rfc.p_mcb->peer_ready
+     || (p_port->rfc.state != RFC_STATE_OPENED))
+    {
+        RFCOMM_TRACE_ERROR ("PORT_GetRemoteMtu() peer not ready or p_port->rfc.state = %d",
+                p_port->rfc.state );
+        return (0);
+    }
+
+    return (p_port->peer_mtu);
+}
+
+/*******************************************************************************
+**
 ** Function         PORT_IsOpening
 **
 ** Description      This function returns TRUE if there is any RFCOMM connection
diff --git a/stack/rfcomm/port_rfc.c b/stack/rfcomm/port_rfc.c
index aaad62a..374b191 100644
--- a/stack/rfcomm/port_rfc.c
+++ b/stack/rfcomm/port_rfc.c
@@ -312,6 +312,7 @@
             problem, they don't disconnect if we send DM */
             rfc_check_mcb_active( p_mcb );
             RFCOMM_TRACE_EVENT( "PORT_ParNegInd: port not found" );
+            GENERATE_VENDOR_LOGS();
             return;
         }
         p_mcb->port_inx[dlci] = p_port->inx;
diff --git a/stack/rfcomm/rfc_l2cap_if.c b/stack/rfcomm/rfc_l2cap_if.c
index 05f4994..6ae3863 100644
--- a/stack/rfcomm/rfc_l2cap_if.c
+++ b/stack/rfcomm/rfc_l2cap_if.c
@@ -35,7 +35,9 @@
 #include "l2cdefs.h"
 #include "rfc_int.h"
 #include "bt_utils.h"
+#include "port_ext.h"
 
+extern fixed_queue_t *btu_general_alarm_queue;
 
 /*
 ** Define Callback functions to be called by L2CAP
@@ -104,10 +106,13 @@
             /* wait random timeout (2 - 12) to resolve collision */
             /* if peer gives up then local device rejects incoming connection and continues as initiator */
             /* if timeout, local device disconnects outgoing connection and continues as acceptor */
-            RFCOMM_TRACE_DEBUG ("RFCOMM_ConnectInd start timer for collision, initiator's LCID(0x%x), acceptor's LCID(0x%x)",
-                                  p_mcb->lcid, p_mcb->pending_lcid);
-
-            rfc_timer_start(p_mcb, (UINT16)(time_get_os_boottime_ms() % 10 + 2));
+            period_ms_t interval_ms = (((time_get_os_boottime_ms() % 20) * 500) + 2000);
+            RFCOMM_TRACE_DEBUG ("RFCOMM_ConnectInd start collision timer = %d ms , initiator's LCID(0x%x), acceptor's LCID(0x%x)",
+                                  interval_ms, p_mcb->lcid, p_mcb->pending_lcid);
+            alarm_set_on_queue(p_mcb->mcb_timer, interval_ms,
+                       rfcomm_mcb_timer_timeout, p_mcb,
+                       btu_general_alarm_queue);
+            GENERATE_VENDOR_LOGS();
             return;
         }
         else
diff --git a/stack/rfcomm/rfc_mx_fsm.c b/stack/rfcomm/rfc_mx_fsm.c
index a12ae96..0d80b26 100644
--- a/stack/rfcomm/rfc_mx_fsm.c
+++ b/stack/rfcomm/rfc_mx_fsm.c
@@ -375,6 +375,8 @@
 *******************************************************************************/
 void rfc_mx_sm_state_wait_sabme (tRFC_MCB *p_mcb, UINT16 event, void *p_data)
 {
+    tPORT   *p_port;
+    int     i;
     RFCOMM_TRACE_EVENT ("rfc_mx_sm_state_wait_sabme - evt:%d", event);
     switch (event)
     {
@@ -414,7 +416,15 @@
 
             p_mcb->state      = RFC_MX_STATE_CONNECTED;
             p_mcb->peer_ready = TRUE;
-            PORT_StartCnf (p_mcb, RFCOMM_SUCCESS);
+            p_port = &rfc_cb.port.port[0];
+            for (i = 0; i < MAX_RFC_PORTS; i++, p_port++)
+            {
+                if (p_port->rfc.p_mcb == p_mcb)
+                {
+                    PORT_StartCnf (p_mcb, RFCOMM_SUCCESS);
+                    break;
+                }
+            }
         }
         return;
 
@@ -603,7 +613,7 @@
 {
     RFCOMM_TRACE_EVENT ("rfc_mx_conf_cnf p_cfg:%08x res:%d ", p_cfg, (p_cfg) ? p_cfg->result : 0);
 
-    if (p_cfg->result != L2CAP_CFG_OK)
+    if (p_cfg && p_cfg->result != L2CAP_CFG_OK)
     {
         if (p_mcb->is_initiator)
         {
diff --git a/stack/rfcomm/rfc_utils.c b/stack/rfcomm/rfc_utils.c
index 2fa7ca8..692d985 100644
--- a/stack/rfcomm/rfc_utils.c
+++ b/stack/rfcomm/rfc_utils.c
@@ -325,6 +325,7 @@
     tPORT *p_port = (tPORT *)data;
 
     rfc_port_sm_execute(p_port, RFC_EVENT_TIMEOUT, NULL);
+    GENERATE_VENDOR_LOGS();
 }
 
 void rfcomm_mcb_timer_timeout(void *data)
@@ -332,6 +333,8 @@
     tRFC_MCB *p_mcb = (tRFC_MCB *)data;
 
     rfc_mx_sm_execute(p_mcb, RFC_EVENT_TIMEOUT, NULL);
+
+    GENERATE_VENDOR_LOGS();
 }
 
 /*******************************************************************************
@@ -375,7 +378,7 @@
 {
     tRFC_MCB *p_mcb = p_port->rfc.p_mcb;
 
-    RFCOMM_TRACE_DEBUG ("rfc_port_closed");
+    RFCOMM_TRACE_WARNING ("rfc_port_closed");
 
     rfc_port_timer_stop (p_port);
 
@@ -436,6 +439,8 @@
         if (p_port->credit_tx > 0)
             p_port->credit_tx--;
 
+        RFCOMM_TRACE_EVENT ("rfc_dec_credit:%d", p_port->credit_tx);
+
         if (p_port->credit_tx == 0)
             p_port->tx.peer_fc = TRUE;
     }
diff --git a/stack/sdp/sdp_api.c b/stack/sdp/sdp_api.c
index f5033cf..a8bada5 100644
--- a/stack/sdp/sdp_api.c
+++ b/stack/sdp/sdp_api.c
@@ -32,6 +32,7 @@
 #include "l2cdefs.h"
 #include "hcidefs.h"
 #include "hcimsgs.h"
+#include "avrc_defs.h"
 
 #include "sdp_api.h"
 #include "sdpint.h"
@@ -1275,3 +1276,35 @@
 
     return(sdp_cb.trace_level);
 }
+
+/****************************************************************************
+**
+** Function         SDP_Dev_Blacklisted_For_Avrcp15
+**
+** Description      This function is called to check if Remote device
+**                  is blacklisted for Avrcp version.
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+BOOLEAN SDP_Dev_Blacklisted_For_Avrcp15 (BD_ADDR addr)
+{
+    int ver;
+    BOOLEAN ret = sdp_dev_blacklisted_for_avrcp15(addr);
+    SDP_TRACE_ERROR("%s", __func__);
+    if (ret != TRUE)
+    {
+        ver = sdp_get_stored_avrc_tg_version (addr);
+        SDP_TRACE_ERROR("Stored AVRC TG version: 0x%x", ver);
+        if (ver >= AVRC_REV_1_4)
+        {
+            ret = FALSE;
+        }
+        else
+        {
+            ret = TRUE;
+        }
+    }
+    SDP_TRACE_ERROR("%s: blacklisted: %d", __func__, ret);
+    return ret;
+}
diff --git a/stack/sdp/sdp_db.c b/stack/sdp/sdp_db.c
index 1c81202..d0d293c 100644
--- a/stack/sdp/sdp_db.c
+++ b/stack/sdp/sdp_db.c
@@ -357,6 +357,8 @@
                 for (yy = xx; yy < sdp_cb.server_db.num_records; yy++, p_rec++)
                 {
                     *p_rec = *(p_rec + 1);
+                    /* Adjust continuation info in the CCB */
+                    sdpu_update_ccb_cont_info(p_rec->record_handle);
 
                     /* Adjust the attribute value pointer for each attribute */
                     for (zz = 0; zz < p_rec->num_attributes; zz++)
@@ -400,7 +402,7 @@
                           UINT32 attr_len, UINT8 *p_val)
 {
 #if SDP_SERVER_ENABLED == TRUE
-    UINT16          xx, yy, zz;
+    UINT16          xx;
     tSDP_RECORD     *p_rec = &sdp_cb.server_db.record[0];
 
 #if (BT_TRACE_VERBOSE == TRUE)
@@ -438,81 +440,84 @@
 #endif
 
     /* Find the record in the database */
-    for (zz = 0; zz < sdp_cb.server_db.num_records; zz++, p_rec++)
+    for (xx = 0; xx < sdp_cb.server_db.num_records; xx++, p_rec++)
     {
         if (p_rec->record_handle == handle)
-        {
-            tSDP_ATTRIBUTE  *p_attr = &p_rec->attribute[0];
-
-            /* Found the record. Now, see if the attribute already exists */
-            for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++)
-            {
-                /* The attribute exists. replace it */
-                if (p_attr->id == attr_id)
-                {
-                    SDP_DeleteAttribute (handle, attr_id);
-                    break;
-                }
-                if (p_attr->id > attr_id)
-                    break;
-            }
-
-            if (p_rec->num_attributes == SDP_MAX_REC_ATTR)
-                return (FALSE);
-
-            /* If not found, see if we can allocate a new entry */
-            if (xx == p_rec->num_attributes)
-                p_attr = &p_rec->attribute[p_rec->num_attributes];
-            else
-            {
-                /* Since the attributes are kept in sorted order, insert ours here */
-                for (yy = p_rec->num_attributes; yy > xx; yy--)
-                    p_rec->attribute[yy] = p_rec->attribute[yy - 1];
-            }
-
-            p_attr->id   = attr_id;
-            p_attr->type = attr_type;
-            p_attr->len  = attr_len;
-
-            if (p_rec->free_pad_ptr + attr_len >= SDP_MAX_PAD_LEN)
-            {
-                /* do truncate only for text string type descriptor */
-                if (attr_type == TEXT_STR_DESC_TYPE)
-                {
-                    SDP_TRACE_WARNING("SDP_AddAttribute: attr_len:%d too long. truncate to (%d)",
-                        attr_len, SDP_MAX_PAD_LEN - p_rec->free_pad_ptr );
-
-                    attr_len = SDP_MAX_PAD_LEN - p_rec->free_pad_ptr;
-                    p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr] = '\0';
-                    p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr+1] = '\0';
-                }
-                else
-                    attr_len = 0;
-            }
-
-            if ((attr_len > 0) && (p_val != 0))
-            {
-                p_attr->len  = attr_len;
-                memcpy (&p_rec->attr_pad[p_rec->free_pad_ptr], p_val, (size_t)attr_len);
-                p_attr->value_ptr = &p_rec->attr_pad[p_rec->free_pad_ptr];
-                p_rec->free_pad_ptr += attr_len;
-            }
-            else if ((attr_len == 0 && p_attr->len != 0) || /* if truncate to 0 length, simply don't add */
-                      p_val == 0)
-            {
-                SDP_TRACE_ERROR("SDP_AddAttribute fail, length exceed maximum: ID %d: attr_len:%d ",
-                    attr_id, attr_len );
-                p_attr->id   = p_attr->type = p_attr->len  = 0;
-                return (FALSE);
-            }
-            p_rec->num_attributes++;
-            return (TRUE);
-        }
+            return SDP_AddAttributetoRecord (p_rec, attr_id, attr_type, attr_len, p_val);
     }
 #endif
     return (FALSE);
 }
 
+BOOLEAN SDP_AddAttributetoRecord (tSDP_RECORD *p_rec, UINT16 attr_id, UINT8 attr_type,
+                                  UINT32 attr_len, UINT8 *p_val)
+{
+    UINT16 xx, yy;
+    tSDP_ATTRIBUTE  *p_attr = &p_rec->attribute[0];
+    /* Found the record. Now, see if the attribute already exists */
+    for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++)
+    {
+        /* The attribute exists. replace it */
+        if (p_attr->id == attr_id)
+        {
+            SDP_DeleteAttributefromRecord (p_rec, attr_id);
+            break;
+        }
+        if (p_attr->id > attr_id)
+            break;
+    }
+
+    if (p_rec->num_attributes == SDP_MAX_REC_ATTR)
+        return (FALSE);
+
+    /* If not found, see if we can allocate a new entry */
+    if (xx == p_rec->num_attributes)
+        p_attr = &p_rec->attribute[p_rec->num_attributes];
+    else
+    {
+        /* Since the attributes are kept in sorted order, insert ours here */
+        for (yy = p_rec->num_attributes; yy > xx; yy--)
+            p_rec->attribute[yy] = p_rec->attribute[yy - 1];
+    }
+
+    p_attr->id   = attr_id;
+    p_attr->type = attr_type;
+    p_attr->len  = attr_len;
+
+    if (p_rec->free_pad_ptr + attr_len >= SDP_MAX_PAD_LEN)
+    {
+        /* do truncate only for text string type descriptor */
+        if (attr_type == TEXT_STR_DESC_TYPE)
+        {
+            SDP_TRACE_WARNING("SDP_AddAttributetoRecord: attr_len:%d too long. truncate to (%d)",
+                attr_len, SDP_MAX_PAD_LEN - p_rec->free_pad_ptr );
+
+            attr_len = SDP_MAX_PAD_LEN - p_rec->free_pad_ptr;
+            p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr] = '\0';
+            p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr+1] = '\0';
+        }
+        else
+            attr_len = 0;
+    }
+
+    if ((attr_len > 0) && (p_val != 0))
+    {
+        p_attr->len  = attr_len;
+        memcpy (&p_rec->attr_pad[p_rec->free_pad_ptr], p_val, (size_t)attr_len);
+        p_attr->value_ptr = &p_rec->attr_pad[p_rec->free_pad_ptr];
+        p_rec->free_pad_ptr += attr_len;
+    }
+    else if ((attr_len == 0 && p_attr->len != 0) || /* if truncate to 0 length, simply don't add */
+              p_val == 0)
+    {
+        SDP_TRACE_ERROR("SDP_AddAttributetoRecord fail, length exceed maximum: ID %d: attr_len:%d ",
+            attr_id, attr_len );
+        p_attr->id   = p_attr->type = p_attr->len  = 0;
+        return (FALSE);
+    }
+    p_rec->num_attributes++;
+    return (TRUE);
+}
 
 /*******************************************************************************
 **
@@ -759,6 +764,36 @@
 #endif
 }
 
+BOOLEAN SDP_AddProfileDescriptorListtoRecord (tSDP_RECORD *prec, UINT16 profile_uuid,
+                                      UINT16 version)
+{
+#if SDP_SERVER_ENABLED == TRUE
+    UINT8 *p;
+    BOOLEAN result;
+    UINT8 *p_buff = (UINT8 *)osi_malloc(sizeof(UINT8) * SDP_MAX_ATTR_LEN);
+
+    p = p_buff + 2;
+
+    /* First, build the profile descriptor list. This consists of a data element sequence. */
+    /* The sequence consists of profile's UUID and version number  */
+    UINT8_TO_BE_STREAM  (p, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
+    UINT16_TO_BE_STREAM (p, profile_uuid);
+
+    UINT8_TO_BE_STREAM  (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
+    UINT16_TO_BE_STREAM (p, version);
+
+    /* Add in type and length fields */
+    *p_buff = (UINT8) ((DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
+    *(p_buff+1) = (UINT8) (p - (p_buff+2));
+
+    result = SDP_AddAttributetoRecord (prec, ATTR_ID_BT_PROFILE_DESC_LIST,DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - p_buff), p_buff);
+    osi_free(p_buff);
+    return result;
+
+#else   /* SDP_SERVER_ENABLED == FALSE */
+    return (FALSE);
+#endif
+}
 
 /*******************************************************************************
 **
@@ -855,56 +890,17 @@
 BOOLEAN SDP_DeleteAttribute (UINT32 handle, UINT16 attr_id)
 {
 #if SDP_SERVER_ENABLED == TRUE
-    UINT16          xx, yy;
+    UINT16          xx;
     tSDP_RECORD     *p_rec = &sdp_cb.server_db.record[0];
-    UINT8           *pad_ptr;
-    UINT32  len;                        /* Number of bytes in the entry */
 
     /* Find the record in the database */
     for (xx = 0; xx < sdp_cb.server_db.num_records; xx++, p_rec++)
     {
         if (p_rec->record_handle == handle)
         {
-            tSDP_ATTRIBUTE  *p_attr = &p_rec->attribute[0];
-
             SDP_TRACE_API("Deleting attr_id 0x%04x for handle 0x%x", attr_id, handle);
-            /* Found it. Now, find the attribute */
-            for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++)
-            {
-                if (p_attr->id == attr_id)
-                {
-                    pad_ptr = p_attr->value_ptr;
-                    len = p_attr->len;
-
-                    if (len)
-                    {
-                        for (yy = 0; yy < p_rec->num_attributes; yy++)
-                        {
-                            if( p_rec->attribute[yy].value_ptr > pad_ptr )
-                                p_rec->attribute[yy].value_ptr -= len;
-                        }
-                    }
-
-                    /* Found it. Shift everything up one */
-                    p_rec->num_attributes--;
-
-                    for (yy = xx; yy < p_rec->num_attributes; yy++, p_attr++)
-                    {
-                        *p_attr = *(p_attr + 1);
-                    }
-
-                    /* adjust attribute values if needed */
-                    if (len)
-                    {
-                        xx = (p_rec->free_pad_ptr - ((pad_ptr+len) -
-                                                  &p_rec->attr_pad[0]));
-                        for( yy=0; yy<xx; yy++, pad_ptr++)
-                            *pad_ptr = *(pad_ptr+len);
-                        p_rec->free_pad_ptr -= len;
-                    }
-                    return (TRUE);
-                }
-            }
+            if (SDP_DeleteAttributefromRecord (p_rec, attr_id))
+                return (TRUE);
         }
     }
 #endif
@@ -912,6 +908,60 @@
     return (FALSE);
 }
 
+BOOLEAN SDP_DeleteAttributefromRecord (tSDP_RECORD *p_rec, UINT16 attr_id)
+{
+    UINT16          xx, yy;
+    tSDP_ATTRIBUTE  *p_attr = &p_rec->attribute[0];
+    UINT8           *pad_ptr;
+    UINT32  len;                        /* Number of bytes in the entry */
+
+    /* Found it. Now, find the attribute */
+    for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++)
+    {
+        if (p_attr->id == attr_id)
+        {
+            pad_ptr = p_attr->value_ptr;
+            len = p_attr->len;
+            if (p_rec->free_pad_ptr + p_attr->len >= SDP_MAX_PAD_LEN)
+            {
+                SDP_TRACE_ERROR("Deleting attr_id 0x%04x len %d exceeds 600", attr_id, len);
+                if (p_attr->type == TEXT_STR_DESC_TYPE)
+                    len = SDP_MAX_PAD_LEN - p_rec->free_pad_ptr;
+                else
+                    len = 0;
+            }
+            if (len)
+            {
+                for (yy = 0; yy < p_rec->num_attributes; yy++)
+                {
+                    if( p_rec->attribute[yy].value_ptr > pad_ptr )
+                        p_rec->attribute[yy].value_ptr -= len;
+                }
+            }
+
+            /* Found it. Shift everything up one */
+            p_rec->num_attributes--;
+
+            for (yy = xx; yy < p_rec->num_attributes; yy++, p_attr++)
+            {
+                *p_attr = *(p_attr + 1);
+            }
+
+            /* adjust attribute values if needed */
+            if (len)
+            {
+                xx = (p_rec->free_pad_ptr - ((pad_ptr+len) -
+                                          &p_rec->attr_pad[0]));
+                for( yy=0; yy<xx; yy++, pad_ptr++)
+                    *pad_ptr = *(pad_ptr+len);
+                p_rec->free_pad_ptr -= len;
+            }
+            return (TRUE);
+        }
+    }
+    return (FALSE);
+}
+
 /*******************************************************************************
 **
 ** Function         SDP_ReadRecord
diff --git a/stack/sdp/sdp_discovery.c b/stack/sdp/sdp_discovery.c
index d2bbc58..9560400 100644
--- a/stack/sdp/sdp_discovery.c
+++ b/stack/sdp/sdp_discovery.c
@@ -98,11 +98,15 @@
             UINT8_TO_BE_STREAM  (p_out, (UUID_DESC_TYPE << 3) | SIZE_FOUR_BYTES);
             UINT32_TO_BE_STREAM (p_out, p_uuid_list->uu.uuid32);
         }
-        else
+        else if (p_uuid_list->len == 16)
         {
             UINT8_TO_BE_STREAM (p_out, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES);
             ARRAY_TO_BE_STREAM (p_out, p_uuid_list->uu.uuid128, p_uuid_list->len);
         }
+        else
+        {
+            SDP_TRACE_ERROR("SDP: Passed Uuid is of Invalid length: %x",p_uuid_list->len);
+        }
     }
 
     /* Now, put in the length */
@@ -371,13 +375,14 @@
     UINT8           type;
 
 #if (SDP_DEBUG_RAW == TRUE)
-    UINT8 num_array[SDP_MAX_LIST_BYTE_COUNT];
+    UINT8 num_array[2 * SDP_MAX_LIST_BYTE_COUNT + 1]; // Need double the space to store hex data
     UINT32 i;
 
     for (i = 0; i < p_ccb->list_len; i++)
     {
         sprintf((char *)&num_array[i*2],"%02X",(UINT8)(p_ccb->rsp_list[i]));
     }
+    (char)num_array[2*i] = '\0';
     SDP_TRACE_WARNING("result :%s",num_array);
 #endif
 
@@ -408,8 +413,9 @@
         {
             cpy_len = list_len;
         }
-        rem_len = SDP_MAX_LIST_BYTE_COUNT - (unsigned int)(p - &p_ccb->rsp_list[0]);
-        if (cpy_len > rem_len) {
+        rem_len = SDP_MAX_LIST_BYTE_COUNT - (unsigned int) (p - &p_ccb->rsp_list[0]);
+        if (cpy_len > rem_len)
+        {
             SDP_TRACE_WARNING("rem_len :%d less than cpy_len:%d", rem_len, cpy_len);
             cpy_len = rem_len;
         }
diff --git a/stack/sdp/sdp_server.c b/stack/sdp/sdp_server.c
index a5aac8e..e295167 100644
--- a/stack/sdp/sdp_server.c
+++ b/stack/sdp/sdp_server.c
@@ -32,15 +32,22 @@
 #include "bt_common.h"
 #include "bt_types.h"
 #include "bt_utils.h"
+#include "bt_trace.h"
 #include "btu.h"
 
 #include "l2cdefs.h"
 #include "hcidefs.h"
 #include "hcimsgs.h"
+#include "avrc_defs.h"
 
 #include "sdp_api.h"
 #include "sdpint.h"
-
+#include "device/include/interop.h"
+#include "btif/include/btif_storage.h"
+#include "device/include/interop_config.h"
+#include <errno.h>
+#include <cutils/properties.h>
+#include <hardware/bluetooth.h>
 
 #if SDP_SERVER_ENABLED == TRUE
 
@@ -50,6 +57,13 @@
 #define SDP_MAX_SERVICE_RSPHDR_LEN      12
 #define SDP_MAX_SERVATTR_RSPHDR_LEN     10
 #define SDP_MAX_ATTR_RSPHDR_LEN         10
+#define PROFILE_VERSION_POSITION         7
+#define SDP_PROFILE_DESC_LENGTH          8
+#define AVRCP_SUPPORTED_FEATURES_POSITION 1
+#define AVRCP_BROWSE_SUPPORT_BITMASK    0x40
+#define AVRCP_CA_SUPPORT_BITMASK        0x01
+#define PBAP_SKIP_GOEP_L2CAP_PSM_LEN    0x06
+#define PBAP_SKIP_SUPP_FEA_LEN          0x08
 
 /********************************************************************************/
 /*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
@@ -66,6 +80,10 @@
                                              UINT16 param_len, UINT8 *p_req,
                                              UINT8 *p_req_end);
 
+static BOOLEAN is_pbap_record_blacklisted (tSDP_ATTRIBUTE attr, BD_ADDR remote_address);
+
+static tSDP_RECORD *sdp_update_pbap_record_if_blacklisted(tSDP_RECORD *p_rec,
+                                      BD_ADDR remote_address);
 
 /********************************************************************************/
 /*                  E R R O R   T E X T   S T R I N G S                         */
@@ -105,6 +123,259 @@
 #define SDP_TEXT_BAD_MAX_RECORDS_LIST   NULL
 #endif
 
+#ifndef SDP_TEXT_BAD_MAX_ATTR_LIST
+#define SDP_TEXT_BAD_MAX_ATTR_LIST   NULL
+#endif
+
+struct blacklist_entry
+{
+    int ver;
+    char addr[3];
+};
+
+int sdp_get_stored_avrc_tg_version(BD_ADDR addr)
+{
+    int stored_ver = AVRC_REV_INVALID;
+    struct blacklist_entry data;
+    FILE *fp;
+
+    SDP_TRACE_DEBUG("%s target BD Addr: %x:%x:%x", __func__,\
+                        addr[0], addr[1], addr[2]);
+
+    fp = fopen(AVRC_PEER_VERSION_CONF_FILE, "rb");
+    if (!fp)
+    {
+       SDP_TRACE_ERROR("%s unable to open AVRC Conf file for read: err: (%s)",\
+                                        __func__, strerror(errno));
+       return stored_ver;
+    }
+    while (fread(&data, sizeof(data), 1, fp) != 0)
+    {
+        SDP_TRACE_DEBUG("Entry: addr = %x:%x:%x, ver = 0x%x",\
+                data.addr[0], data.addr[1], data.addr[2], data.ver);
+        if(!memcmp(addr, data.addr, 3))
+        {
+            stored_ver = data.ver;
+            SDP_TRACE_DEBUG("Entry found with version: 0x%x", stored_ver);
+            break;
+        }
+    }
+    fclose(fp);
+    return stored_ver;
+}
+
+/****************************************************************************
+**
+** Function         sdp_dev_blacklisted_for_avrcp15
+**
+** Description      This function is called to check if Remote device
+**                  is blacklisted for Avrcp version.
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+BOOLEAN sdp_dev_blacklisted_for_avrcp15 (BD_ADDR addr)
+{
+    bt_bdaddr_t remote_bdaddr;
+    bdcpy(remote_bdaddr.address, addr);
+
+    if (interop_match_addr(INTEROP_ADV_AVRCP_VER_1_3, &remote_bdaddr)) {
+        bt_property_t prop_name;
+        bt_bdname_t bdname;
+
+        BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_BDNAME,
+                               sizeof(bt_bdname_t), &bdname);
+        if (btif_storage_get_remote_device_property(&remote_bdaddr,
+                                              &prop_name) != BT_STATUS_SUCCESS)
+        {
+            SDP_TRACE_ERROR("%s: BT_PROPERTY_BDNAME failed, returning false", __func__);
+            return FALSE;
+        }
+
+        if (strlen((const char *)bdname.name) != 0 &&
+            interop_match_name(INTEROP_ADV_AVRCP_VER_1_3, (const char *)bdname.name))
+        {
+            SDP_TRACE_DEBUG("%s: advertise AVRCP version 1.3 for device", __func__);
+            return TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
+/*************************************************************************************
+**
+** Function        sdp_fallback_avrcp_version
+**
+** Description     Checks if UUID is AV Remote Control, attribute id
+**                 is Profile descriptor list and remote BD address
+**                 matches device blacklist, change Avrcp version to 1.3
+**
+** Returns         BOOLEAN
+**
+***************************************************************************************/
+BOOLEAN sdp_fallback_avrcp_version (tSDP_ATTRIBUTE *p_attr, BD_ADDR remote_address)
+{
+    char a2dp_role[PROPERTY_VALUE_MAX] = "false";
+    if ((p_attr->id == ATTR_ID_BT_PROFILE_DESC_LIST) &&
+        (p_attr->len >= SDP_PROFILE_DESC_LENGTH))
+    {
+        /* As per current DB implementation UUID is condidered as 16 bit */
+        if (((p_attr->value_ptr[3] << 8) | (p_attr->value_ptr[4])) ==
+                UUID_SERVCLASS_AV_REMOTE_CONTROL)
+        {
+            int ver;
+            if (sdp_dev_blacklisted_for_avrcp15 (remote_address))
+            {
+                p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x03; // Update AVRCP version as 1.3
+                SDP_TRACE_ERROR("SDP Change AVRCP Version = 0x%x",
+                         p_attr->value_ptr[PROFILE_VERSION_POSITION]);
+                return TRUE;
+            }
+            property_get("persist.service.bt.a2dp.sink", a2dp_role, "false");
+            if (!strncmp("false", a2dp_role, 5)) {
+                ver = sdp_get_stored_avrc_tg_version (remote_address);
+                if (ver != AVRC_REV_INVALID)
+                {
+                    SDP_TRACE_DEBUG("Stored AVRC TG version: 0x%x", ver);
+                    p_attr->value_ptr[PROFILE_VERSION_POSITION] = (UINT8)(ver & 0x00ff);
+                    SDP_TRACE_DEBUG("SDP Change AVRCP Version = 0x%x",
+                                 p_attr->value_ptr[PROFILE_VERSION_POSITION]);
+#if (defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE))
+                    if (ver != AVRC_REV_1_6)
+#else
+#if (defined(SDP_AVRCP_1_5) && (SDP_AVRCP_1_5 == TRUE))
+                    if (ver != AVRC_REV_1_5)
+#endif
+#endif
+                        return TRUE;
+                    else
+                        return FALSE;
+                }
+                else
+                {
+                    p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x03; // Update AVRCP ver as 1.3
+                    SDP_TRACE_DEBUG("Device not stored, Change AVRCP Version = 0x%x",
+                             p_attr->value_ptr[PROFILE_VERSION_POSITION]);
+                    return TRUE;
+                }
+            }
+        }
+    }
+    return FALSE;
+}
+
+/*************************************************************************************
+**
+** Function        sdp_reset_avrcp_browsing_bit
+**
+** Description     Checks if Service Class ID is AV Remote Control TG, attribute id
+**                 is Supported features and remote BD address
+**                 matches device blacklist, reset Browsing Bit
+**
+** Returns         BOOLEAN
+**
+***************************************************************************************/
+BOOLEAN sdp_reset_avrcp_browsing_bit (tSDP_ATTRIBUTE attr, tSDP_ATTRIBUTE *p_attr,
+BD_ADDR                                                                      remote_address)
+{
+    if ((p_attr->id == ATTR_ID_SUPPORTED_FEATURES) && (attr.id == ATTR_ID_SERVICE_CLASS_ID_LIST) &&
+        (((attr.value_ptr[1] << 8) | (attr.value_ptr[2])) == UUID_SERVCLASS_AV_REM_CTRL_TARGET))
+    {
+        int ver;
+        if (sdp_dev_blacklisted_for_avrcp15 (remote_address))
+        {
+            SDP_TRACE_ERROR("Reset Browse feature bitmask");
+            p_attr->value_ptr[AVRCP_SUPPORTED_FEATURES_POSITION] &= ~AVRCP_BROWSE_SUPPORT_BITMASK;
+            return TRUE;
+        }
+        ver = sdp_get_stored_avrc_tg_version (remote_address);
+        SDP_TRACE_ERROR("Stored AVRC TG version: 0x%x", ver);
+        if ((ver < AVRC_REV_1_4) || (ver == AVRC_REV_INVALID))
+        {
+            SDP_TRACE_ERROR("Reset Browse feature bitmask");
+            p_attr->value_ptr[AVRCP_SUPPORTED_FEATURES_POSITION] &= ~AVRCP_BROWSE_SUPPORT_BITMASK;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/*************************************************************************************
+**
+** Function        sdp_change_hfp_version
+**
+** Description     Checks if UUID is AG_HANDSFREE, attribute id
+**                 is Profile descriptor list and remote BD address
+**                 matches device blacklist, change hfp version to 1.7
+**
+** Returns         BOOLEAN
+**
+***************************************************************************************/
+BOOLEAN sdp_change_hfp_version (tSDP_ATTRIBUTE *p_attr, BD_ADDR remote_address)
+{
+    bool is_blacklisted = FALSE;
+    char value[PROPERTY_VALUE_MAX];
+    if ((p_attr->id == ATTR_ID_BT_PROFILE_DESC_LIST) &&
+        (p_attr->len >= SDP_PROFILE_DESC_LENGTH))
+    {
+        /* As per current DB implementation UUID is condidered as 16 bit */
+        if (((p_attr->value_ptr[3] << 8) | (p_attr->value_ptr[4])) ==
+                UUID_SERVCLASS_HF_HANDSFREE)
+        {
+            bt_bdaddr_t remote_bdaddr;
+            bdcpy(remote_bdaddr.address, remote_address);
+            is_blacklisted = interop_database_match_addr(INTEROP_HFP_1_7_BLACKLIST, (bt_bdaddr_t *)&remote_bdaddr);
+            SDP_TRACE_DEBUG("%s: HF version is 1.7 for BD addr: %x:%x:%x",\
+                           __func__, remote_address[0], remote_address[1], remote_address[2]);
+            /* For PTS we should show AG's HFP version as 1.7 */
+            if (is_blacklisted ||
+                (property_get("bt.pts.certification", value, "false") &&
+                 strcmp(value, "true") == 0))
+            {
+                p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x07; // Update HFP version as 1.7
+                SDP_TRACE_ERROR("SDP Change HFP Version = 0x%x",
+                         p_attr->value_ptr[PROFILE_VERSION_POSITION]);
+                return TRUE;
+            }
+        }
+    }
+    return FALSE;
+}
+
+/*************************************************************************************
+**
+** Function        sdp_reset_avrcp_cover_art_bit
+**
+** Description     Checks if Service Class ID is AV Remote Control TG, attribute id
+**                 is Supported features and remote BD address
+**                 matches device blacklist, reset Cover Art Bit
+**
+** Returns         BOOLEAN
+**
+***************************************************************************************/
+
+BOOLEAN sdp_reset_avrcp_cover_art_bit (tSDP_ATTRIBUTE attr, tSDP_ATTRIBUTE *p_attr,
+                                                 BD_ADDR remote_address)
+{
+    if ((p_attr->id == ATTR_ID_SUPPORTED_FEATURES) && (attr.id == ATTR_ID_SERVICE_CLASS_ID_LIST) &&
+        (((attr.value_ptr[1] << 8) | (attr.value_ptr[2])) == UUID_SERVCLASS_AV_REM_CTRL_TARGET))
+    {
+        int ver;
+        ver = sdp_get_stored_avrc_tg_version (remote_address);
+        SDP_TRACE_ERROR("Stored AVRC TG version: 0x%x", ver);
+        if ((ver < AVRC_REV_1_6) || (ver == AVRC_REV_INVALID))
+        {
+            SDP_TRACE_ERROR("Reset Cover Art feature bitmask +1, 0x%x", p_attr->value_ptr[AVRCP_SUPPORTED_FEATURES_POSITION+1]);
+            SDP_TRACE_ERROR("Reset Cover Art feature bitmask -1, 0x%x", p_attr->value_ptr[AVRCP_SUPPORTED_FEATURES_POSITION-1]);
+            p_attr->value_ptr[AVRCP_SUPPORTED_FEATURES_POSITION-1] &= ~AVRCP_CA_SUPPORT_BITMASK;
+            SDP_TRACE_ERROR("Reset Cover Art feature bitmask, new -1, 0x%x", p_attr->value_ptr[AVRCP_SUPPORTED_FEATURES_POSITION-1]);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
 /*******************************************************************************
 **
 ** Function         sdp_server_handle_client_req
@@ -217,6 +488,12 @@
     }
     BE_STREAM_TO_UINT16 (max_replies, p_req);
 
+    if (!max_replies)
+    {
+        sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX, SDP_TEXT_BAD_MAX_ATTR_LIST);
+        return;
+    }
+
     if (max_replies > SDP_MAX_RECORDS)
         max_replies = SDP_MAX_RECORDS;
 
@@ -252,10 +529,20 @@
             return;
         }
 
+        if (p_req != p_req_end)
+        {
+            sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_PDU_SIZE, SDP_TEXT_BAD_HEADER);
+            return;
+        }
         rem_handles = num_rsp_handles - cont_offset;    /* extract the remaining handles */
     }
     else
     {
+        if (p_req+1 != p_req_end)
+        {
+            sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_PDU_SIZE, SDP_TEXT_BAD_HEADER);
+            return;
+        }
         rem_handles = num_rsp_handles;
         cont_offset = 0;
         p_ccb->cont_offset = 0;
@@ -340,6 +627,10 @@
     tSDP_RECORD     *p_rec;
     tSDP_ATTRIBUTE  *p_attr;
     BOOLEAN         is_cont = FALSE;
+    BOOLEAN         is_avrcp_fallback = FALSE;
+    BOOLEAN         is_avrcp_browse_bit_reset = FALSE;
+    BOOLEAN         is_hfp_fallback = FALSE;
+    BOOLEAN         is_avrcp_ca_bit_reset = FALSE;
     UINT16          attr_len;
 
     if (p_req + sizeof(rec_handle) + sizeof(max_list_len) > p_req_end) {
@@ -357,6 +648,12 @@
     BE_STREAM_TO_UINT16 (max_list_len, p_req);
     param_len -= sizeof(max_list_len);
 
+    if (!max_list_len)
+    {
+        sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX, SDP_TEXT_BAD_MAX_ATTR_LIST);
+        return;
+    }
+
     if (max_list_len > (p_ccb->rem_mtu_size - SDP_MAX_ATTR_RSPHDR_LEN))
         max_list_len = p_ccb->rem_mtu_size - SDP_MAX_ATTR_RSPHDR_LEN;
 
@@ -385,6 +682,8 @@
         return;
     }
 
+    p_rec = sdp_update_pbap_record_if_blacklisted(p_rec, p_ccb->device_address);
+
     /* Free and reallocate buffer */
     osi_free(p_ccb->rsp_list);
     p_ccb->rsp_list = (UINT8 *)osi_malloc(max_list_len);
@@ -404,6 +703,11 @@
                                     SDP_TEXT_BAD_CONT_INX);
             return;
         }
+        if (p_req != p_req_end)
+        {
+            sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_PDU_SIZE, SDP_TEXT_BAD_HEADER);
+            return;
+        }
         is_cont = TRUE;
 
         /* Initialise for continuation response */
@@ -411,11 +715,18 @@
         attr_seq.attr_entry[p_ccb->cont_info.next_attr_index].start =
             p_ccb->cont_info.next_attr_start_id;
     } else {
+        if (p_req+1 != p_req_end)
+        {
+            sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_PDU_SIZE, SDP_TEXT_BAD_HEADER);
+            return;
+        }
+
         p_ccb->cont_offset = 0;
         p_rsp = &p_ccb->rsp_list[3];    /* Leave space for data elem descr */
 
         /* Reset continuation parameters in p_ccb */
         p_ccb->cont_info.prev_sdp_rec = NULL;
+        p_ccb->cont_info.curr_sdp_rec = NULL;
         p_ccb->cont_info.next_attr_index = 0;
         p_ccb->cont_info.attr_offset = 0;
     }
@@ -427,6 +738,20 @@
 
         if (p_attr)
         {
+#if ((defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE)) || \
+        (defined(SDP_AVRCP_1_5) && (SDP_AVRCP_1_5 == TRUE)))
+            /* Check for UUID Remote Control and Remote BD address  */
+            is_avrcp_fallback = sdp_fallback_avrcp_version (p_attr, p_ccb->device_address);
+#if (defined(AVCT_BROWSE_INCLUDED)&&(AVCT_BROWSE_INCLUDED == TRUE))
+            is_avrcp_browse_bit_reset = sdp_reset_avrcp_browsing_bit(
+                        p_rec->attribute[1], p_attr, p_ccb->device_address);
+#endif
+#if (defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE))
+            is_avrcp_ca_bit_reset = sdp_reset_avrcp_cover_art_bit(
+                        p_rec->attribute[1], p_attr, p_ccb->device_address);
+#endif
+#endif
+            is_hfp_fallback = sdp_change_hfp_version (p_attr, p_ccb->device_address);
             /* Check if attribute fits. Assume 3-byte value type/length */
             rem_len = max_list_len - (INT16) (p_rsp - &p_ccb->rsp_list[0]);
 
@@ -487,8 +812,80 @@
 
                 xx--;
             }
+            if (is_avrcp_fallback)
+            {
+#if (defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE))
+                /* Update AVRCP version back to 1.6 */
+                p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x06;
+#else
+#if (defined(SDP_AVRCP_1_5) && (SDP_AVRCP_1_5 == TRUE))
+                /* Update AVRCP version back to 1.5 */
+                p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x05;
+#endif
+#endif
+                is_avrcp_fallback = FALSE;
+            }
+            if (is_avrcp_browse_bit_reset)
+            {
+                /* Restore Browsing bit */
+                SDP_TRACE_ERROR("Restore Browsing bit");
+                p_attr->value_ptr[AVRCP_SUPPORTED_FEATURES_POSITION]
+                                        |= AVRCP_BROWSE_SUPPORT_BITMASK;
+                is_avrcp_browse_bit_reset = FALSE;
+            }
+            if (is_hfp_fallback)
+            {
+                SDP_TRACE_ERROR("Restore HFP version to 1.6");
+                /* Update HFP version back to 1.6 */
+                p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x06;
+                is_hfp_fallback = FALSE;
+            }
+            if (is_avrcp_ca_bit_reset)
+            {
+                /* Restore Cover Art bit */
+                SDP_TRACE_ERROR("Restore Cover Art bit");
+                p_attr->value_ptr[AVRCP_SUPPORTED_FEATURES_POSITION - 1]
+                                        |= AVRCP_CA_SUPPORT_BITMASK;
+                is_avrcp_ca_bit_reset = FALSE;
+            }
         }
     }
+    if (is_avrcp_fallback)
+    {
+#if (defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE))
+        /* Update AVRCP version back to 1.6 */
+        p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x06;
+#else
+#if (defined(SDP_AVRCP_1_5) && (SDP_AVRCP_1_5 == TRUE))
+        /* Update AVRCP version back to 1.5 */
+        p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x05;
+#endif
+#endif
+        is_avrcp_fallback = FALSE;
+    }
+    if (is_avrcp_browse_bit_reset)
+    {
+        /* Restore Browsing bit */
+        SDP_TRACE_ERROR("Restore Browsing bit");
+        p_attr->value_ptr[AVRCP_SUPPORTED_FEATURES_POSITION]
+                                    |= AVRCP_BROWSE_SUPPORT_BITMASK;
+        is_avrcp_browse_bit_reset = FALSE;
+    }
+    if (is_hfp_fallback)
+    {
+        SDP_TRACE_ERROR("Restore HFP version to 1.6");
+        /* Update HFP version back to 1.6 */
+        p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x06;
+        is_hfp_fallback = FALSE;
+    }
+    if (is_avrcp_ca_bit_reset)
+    {
+        /* Restore Cover Art bit */
+        SDP_TRACE_ERROR("Restore Cover Art bit");
+        p_attr->value_ptr[AVRCP_SUPPORTED_FEATURES_POSITION - 1]
+                                |= AVRCP_CA_SUPPORT_BITMASK;
+        is_avrcp_ca_bit_reset = FALSE;
+    }
     /* If all the attributes have been accomodated in p_rsp,
        reset next_attr_index */
     if (xx == attr_seq.num_attr)
@@ -586,11 +983,18 @@
     UINT8           *p_rsp, *p_rsp_start, *p_rsp_param_len;
     UINT16          rsp_param_len, xx;
     tSDP_RECORD    *p_rec;
+    tSDP_RECORD    *p_prev_rec;
     tSDP_ATTR_SEQ   attr_seq, attr_seq_sav;
     tSDP_ATTRIBUTE *p_attr;
+    BT_HDR         *p_buf;
     BOOLEAN         maxxed_out = FALSE, is_cont = FALSE;
-    UINT8           *p_seq_start;
+    BOOLEAN         is_avrcp_fallback = FALSE;
+    BOOLEAN         is_avrcp_browse_bit_reset = FALSE;
+    BOOLEAN         is_hfp_fallback = FALSE;
+    BOOLEAN         is_avrcp_ca_bit_reset = FALSE;
+    UINT8           *p_seq_start = NULL;
     UINT16          seq_len, attr_len;
+    UINT16          blacklist_skip_len = 0;
     UNUSED(p_req_end);
 
     /* Extract the UUID sequence to search for */
@@ -605,6 +1009,12 @@
     /* Get the max list length we can send. Cap it at our max list length. */
     BE_STREAM_TO_UINT16 (max_list_len, p_req);
 
+    if (!max_list_len)
+    {
+        sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX, SDP_TEXT_BAD_MAX_ATTR_LIST);
+        return;
+    }
+
     if (max_list_len > (p_ccb->rem_mtu_size - SDP_MAX_SERVATTR_RSPHDR_LEN))
         max_list_len = p_ccb->rem_mtu_size - SDP_MAX_SERVATTR_RSPHDR_LEN;
 
@@ -644,6 +1054,11 @@
                                      SDP_TEXT_BAD_CONT_INX);
             return;
         }
+        if (p_req != p_req_end)
+        {
+            sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_PDU_SIZE, SDP_TEXT_BAD_HEADER);
+            return;
+        }
         is_cont = TRUE;
 
         /* Initialise for continuation response */
@@ -651,11 +1066,18 @@
         attr_seq.attr_entry[p_ccb->cont_info.next_attr_index].start =
             p_ccb->cont_info.next_attr_start_id;
     } else {
+        if (p_req+1 != p_req_end)
+        {
+            sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_PDU_SIZE, SDP_TEXT_BAD_HEADER);
+            return;
+        }
+
         p_ccb->cont_offset = 0;
         p_rsp = &p_ccb->rsp_list[3];    /* Leave space for data elem descr */
 
         /* Reset continuation parameters in p_ccb */
         p_ccb->cont_info.prev_sdp_rec = NULL;
+        p_ccb->cont_info.curr_sdp_rec = NULL;
         p_ccb->cont_info.next_attr_index = 0;
         p_ccb->cont_info.last_attr_seq_desc_sent = FALSE;
         p_ccb->cont_info.attr_offset = 0;
@@ -664,6 +1086,35 @@
     /* Get a list of handles that match the UUIDs given to us */
     for (p_rec = sdp_db_service_search (p_ccb->cont_info.prev_sdp_rec, &uid_seq); p_rec; p_rec = sdp_db_service_search (p_rec, &uid_seq))
     {
+        p_ccb->cont_info.curr_sdp_rec = p_rec;
+        /* Store the actual record pointer which would be reused later */
+        p_prev_rec = p_rec;
+        p_rec = sdp_update_pbap_record_if_blacklisted(p_rec, p_ccb->device_address);
+        if (p_rec != p_prev_rec) {
+            /* Remote device is blacklisted for PBAP, calculate the reduction in length */
+            for (xx = p_ccb->cont_info.next_attr_index; xx < attr_seq_sav.num_attr; xx++) {
+                if (attr_seq_sav.attr_entry[xx].start == attr_seq_sav.attr_entry[xx].end) {
+                    if (attr_seq_sav.attr_entry[xx].start == ATTR_ID_GOEP_L2CAP_PSM) {
+                        blacklist_skip_len += PBAP_SKIP_GOEP_L2CAP_PSM_LEN;
+                        SDP_TRACE_ERROR("%s: ATTR_ID_GOEP_L2CAP_PSM requested,"
+                            " need to reduce length by %d", __func__,
+                            blacklist_skip_len);
+                    } else if (attr_seq_sav.attr_entry[xx].start ==
+                        ATTR_ID_PBAP_SUPPORTED_FEATURES) {
+                        blacklist_skip_len += PBAP_SKIP_SUPP_FEA_LEN;
+                        SDP_TRACE_DEBUG("%s: ATTR_ID_PBAP_SUPPORTED_FEATURES requested,"
+                            " need to reduce length by %d", __func__,
+                            blacklist_skip_len);
+                    }
+                } else {
+                    blacklist_skip_len = PBAP_SKIP_GOEP_L2CAP_PSM_LEN +
+                        PBAP_SKIP_SUPP_FEA_LEN;
+                    SDP_TRACE_DEBUG("%s: All attributes requested"
+                        " need to reduce length by %d", __func__,
+                        blacklist_skip_len);
+                }
+            }
+        }
         /* Allow space for attribute sequence type and length */
         p_seq_start = p_rsp;
         if (p_ccb->cont_info.last_attr_seq_desc_sent == FALSE)
@@ -687,6 +1138,20 @@
 
             if (p_attr)
             {
+#if ((defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE)) || \
+        (defined(SDP_AVRCP_1_5) && (SDP_AVRCP_1_5 == TRUE)))
+                /* Check for UUID Remote Control and Remote BD address  */
+                is_avrcp_fallback = sdp_fallback_avrcp_version (p_attr, p_ccb->device_address);
+#if (defined(AVCT_BROWSE_INCLUDED)&&(AVCT_BROWSE_INCLUDED == TRUE))
+                is_avrcp_browse_bit_reset = sdp_reset_avrcp_browsing_bit(
+                            p_rec->attribute[1], p_attr, p_ccb->device_address);
+#endif
+#if (defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE))
+                is_avrcp_ca_bit_reset = sdp_reset_avrcp_cover_art_bit(
+                            p_rec->attribute[1], p_attr, p_ccb->device_address);
+#endif
+#endif
+                is_hfp_fallback = sdp_change_hfp_version (p_attr, p_ccb->device_address);
                 /* Check if attribute fits. Assume 3-byte value type/length */
                 rem_len = max_list_len - (INT16) (p_rsp - &p_ccb->rsp_list[0]);
 
@@ -752,8 +1217,80 @@
 
                     xx--;
                 }
+                if (is_avrcp_fallback)
+                {
+#if (defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE))
+                    /* Update AVRCP version back to 1.6 */
+                    p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x06;
+#else
+#if (defined(SDP_AVRCP_1_5) && (SDP_AVRCP_1_5 == TRUE))
+                    /* Update AVRCP version back to 1.5 */
+                    p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x05;
+#endif
+#endif
+                    is_avrcp_fallback = FALSE;
+                }
+                if (is_avrcp_browse_bit_reset)
+                {
+                    /* Restore Browsing bit */
+                    SDP_TRACE_ERROR("Restore Browsing bit");
+                    p_attr->value_ptr[AVRCP_SUPPORTED_FEATURES_POSITION]
+                                            |= AVRCP_BROWSE_SUPPORT_BITMASK;
+                    is_avrcp_browse_bit_reset = FALSE;
+                }
+                if (is_hfp_fallback)
+                {
+                    SDP_TRACE_ERROR("Restore HFP version to 1.6");
+                    /* Update HFP version back to 1.6 */
+                    p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x06;
+                    is_hfp_fallback = FALSE;
+                }
+                if (is_avrcp_ca_bit_reset)
+                {
+                    /* Restore Cover Art bit */
+                    SDP_TRACE_ERROR("Restore Cover Art bit");
+                    p_attr->value_ptr[AVRCP_SUPPORTED_FEATURES_POSITION - 1]
+                                            |= AVRCP_CA_SUPPORT_BITMASK;
+                    is_avrcp_ca_bit_reset = FALSE;
+                }
             }
         }
+        if (is_avrcp_fallback)
+        {
+#if (defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE))
+            /* Update AVRCP version back to 1.6 */
+            p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x06;
+#else
+#if (defined(SDP_AVRCP_1_5) && (SDP_AVRCP_1_5 == TRUE))
+            /* Update AVRCP version back to 1.5 */
+            p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x05;
+#endif
+#endif
+            is_avrcp_fallback = FALSE;
+        }
+        if (is_avrcp_browse_bit_reset)
+        {
+            /* Restore Browsing bit */
+            SDP_TRACE_ERROR("Restore Browsing bit");
+            p_attr->value_ptr[AVRCP_SUPPORTED_FEATURES_POSITION]
+                                    |= AVRCP_BROWSE_SUPPORT_BITMASK;
+            is_avrcp_browse_bit_reset = FALSE;
+        }
+        if (is_hfp_fallback)
+        {
+            SDP_TRACE_ERROR("Restore HFP version to 1.6");
+            /* Update HFP version back to 1.6 */
+            p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x06;
+            is_hfp_fallback = FALSE;
+        }
+        if (is_avrcp_ca_bit_reset)
+        {
+            /* Restore Cover Art bit */
+            SDP_TRACE_ERROR("Restore Cover Art bit");
+            p_attr->value_ptr[AVRCP_SUPPORTED_FEATURES_POSITION - 1]
+                                    |= AVRCP_CA_SUPPORT_BITMASK;
+            is_avrcp_ca_bit_reset = FALSE;
+        }
 
         /* Go back and put the type and length into the buffer */
         if (p_ccb->cont_info.last_attr_seq_desc_sent == FALSE)
@@ -761,8 +1298,15 @@
             seq_len = sdpu_get_attrib_seq_len(p_rec, &attr_seq_sav);
             if (seq_len != 0)
             {
-                UINT8_TO_BE_STREAM  (p_seq_start, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_WORD);
-                UINT16_TO_BE_STREAM (p_seq_start, seq_len);
+                if (p_seq_start)
+                {
+                    UINT8_TO_BE_STREAM  (p_seq_start, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_WORD);
+                    UINT16_TO_BE_STREAM (p_seq_start, seq_len);
+                }
+                else
+                {
+                    SDP_TRACE_DEBUG("SDP service and attribute rsp: Attribute sequence p_seq_start is NULL");
+                }
 
                 if (maxxed_out)
                     p_ccb->cont_info.last_attr_seq_desc_sent = TRUE;
@@ -779,6 +1323,8 @@
 
         /* Reset the next attr index */
         p_ccb->cont_info.next_attr_index = 0;
+        /* restore the record pointer.*/
+        p_rec = p_prev_rec;
         p_ccb->cont_info.prev_sdp_rec = p_rec;
         p_ccb->cont_info.last_attr_seq_desc_sent = FALSE;
     }
@@ -813,6 +1359,13 @@
     {
         /* Get the total list length for requested uid and attribute sequence */
         p_ccb->list_len = sdpu_get_list_len(&uid_seq, &attr_seq_sav) + 3;
+        if (blacklist_skip_len &&
+            p_ccb->list_len > blacklist_skip_len) {
+            p_ccb->list_len -= blacklist_skip_len;
+            SDP_TRACE_DEBUG("%s: reducing list_len by %d for blacklisted device",
+                __func__, blacklist_skip_len);
+            blacklist_skip_len = 0;
+        }
         /* Put in the sequence header (2 or 3 bytes) */
         if (p_ccb->list_len > 255)
         {
@@ -833,7 +1386,7 @@
     }
 
     /* Get a buffer to use to build the response */
-    BT_HDR *p_buf = (BT_HDR *)osi_malloc(SDP_DATA_BUF_SIZE);
+    p_buf = (BT_HDR *)osi_malloc(SDP_DATA_BUF_SIZE);
     p_buf->offset = L2CAP_MIN_OFFSET;
     p_rsp = p_rsp_start = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
 
@@ -854,6 +1407,14 @@
 
     p_ccb->cont_offset += len_to_send;
 
+    if (blacklist_skip_len &&
+        p_ccb->list_len > blacklist_skip_len) {
+        p_ccb->list_len -= blacklist_skip_len;
+        SDP_TRACE_DEBUG("%s: reducing list_len by %d for blacklisted device",
+            __func__, blacklist_skip_len);
+        blacklist_skip_len = 0;
+    }
+
     /* If anything left to send, continuation needed */
     if (p_ccb->cont_offset < p_ccb->list_len)
     {
@@ -877,4 +1438,97 @@
     L2CA_DataWrite (p_ccb->connection_id, p_buf);
 }
 
+/*************************************************************************************
+**
+** Function        is_pbap_record_blacklisted
+**
+** Description     Checks if given PBAP record is for PBAP PSE and blacklisted
+**
+** Returns         BOOLEAN
+**
+***************************************************************************************/
+static BOOLEAN is_pbap_record_blacklisted (tSDP_ATTRIBUTE attr,
+                                      BD_ADDR remote_address)
+{
+    if ((attr.id == ATTR_ID_SERVICE_CLASS_ID_LIST) &&
+        (((attr.value_ptr[1] << 8) | (attr.value_ptr[2])) ==
+        UUID_SERVCLASS_PBAP_PSE))
+    {
+        bt_bdaddr_t remote_bdaddr;
+        bdcpy(remote_bdaddr.address, remote_address);
+
+        bt_property_t prop_name;
+        bt_bdname_t bdname;
+
+        memset(&bdname, 0, sizeof(bt_bdname_t));
+        BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_BDNAME,
+                               sizeof(bt_bdname_t), &bdname);
+        if (btif_storage_get_remote_device_property(&remote_bdaddr,
+                                              &prop_name) != BT_STATUS_SUCCESS) {
+            SDP_TRACE_DEBUG("%s: BT_PROPERTY_BDNAME failed", __func__);
+        }
+        if (interop_match_addr(INTEROP_ADV_PBAP_VER_1_1, &remote_bdaddr) ||
+           (strlen((const char *)bdname.name) != 0 &&
+            interop_match_name(INTEROP_ADV_PBAP_VER_1_1,
+            (const char *)bdname.name))) {
+            SDP_TRACE_DEBUG("%s: device is blacklisted for pbap version downgrade", __func__);
+            return TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
+/*************************************************************************************
+**
+** Function        sdp_update_pbap_record_if_blacklisted
+**
+** Description     updates pbap record after checking if blacklisted
+**
+** Returns         the address of updated record
+**
+***************************************************************************************/
+static tSDP_RECORD *sdp_update_pbap_record_if_blacklisted(tSDP_RECORD *p_rec,
+                                      BD_ADDR remote_address)
+{
+    static tSDP_RECORD pbap_temp_sdp_rec;
+    static BOOLEAN is_blacklisted_rec_created = FALSE;
+
+    /* Check if the given SDP record is blacklisted and requires updatiion */
+    if (is_pbap_record_blacklisted(p_rec->attribute[1], remote_address)) {
+        if (is_blacklisted_rec_created)
+            return &pbap_temp_sdp_rec;
+
+        bool status = TRUE;
+        int xx;
+        UINT8 supported_repositories = 0x03;
+        UINT16 legacy_version = 0x0101;
+        memset(&pbap_temp_sdp_rec, 0, sizeof(tSDP_RECORD));
+
+        tSDP_ATTRIBUTE  *p_attr = &p_rec->attribute[0];
+
+        /* Copying contents of the PBAP PSE record to a temporary record */
+        for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++)
+            SDP_AddAttributetoRecord (&pbap_temp_sdp_rec, p_attr->id,
+            p_attr->type, p_attr->len, p_attr->value_ptr);
+
+        status &= SDP_DeleteAttributefromRecord (&pbap_temp_sdp_rec,
+            ATTR_ID_PBAP_SUPPORTED_FEATURES);
+        status &= SDP_DeleteAttributefromRecord (&pbap_temp_sdp_rec,
+            ATTR_ID_GOEP_L2CAP_PSM);
+        status &= SDP_AddAttributetoRecord (&pbap_temp_sdp_rec,
+            ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, (UINT32)1,
+            (UINT8*)&supported_repositories);
+        status &= SDP_AddProfileDescriptorListtoRecord(&pbap_temp_sdp_rec,
+            UUID_SERVCLASS_PHONE_ACCESS, legacy_version);
+        if (!status) {
+            SDP_TRACE_ERROR("%s() FAILED", __func__);
+            return p_rec;
+        }
+        is_blacklisted_rec_created = TRUE;
+        return &pbap_temp_sdp_rec;
+    }
+    return p_rec;
+}
+
 #endif  /* SDP_SERVER_ENABLED == TRUE */
diff --git a/stack/sdp/sdp_utils.c b/stack/sdp/sdp_utils.c
index cbfb874..c5fd811 100644
--- a/stack/sdp/sdp_utils.c
+++ b/stack/sdp/sdp_utils.c
@@ -158,6 +158,41 @@
     osi_free_and_reset((void **)&p_ccb->rsp_list);
 }
 
+/*******************************************************************************
+**
+** Function         sdpu_update_ccb_cont_info
+**
+** Description      This function updates CCB's continuation information in the
+**                  case of a record being moved up one place in DB following
+**                  deletion of a record above.
+**
+** Returns          void
+**
+*******************************************************************************/
+void sdpu_update_ccb_cont_info (UINT32 handle)
+{
+    UINT16       xx;
+    tCONN_CB     *p_ccb;
+
+    /* Look through each connection control block */
+    for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++)
+    {
+        if ((p_ccb->con_state != SDP_STATE_IDLE) && (p_ccb->cont_info.curr_sdp_rec) && (p_ccb->cont_info.curr_sdp_rec->record_handle == handle))
+        {
+            if (handle == sdp_cb.server_db.record[0].record_handle)
+            {
+                /* The record is moved to the top of database. Resetting the prev_sdp_rec to NULL */
+                p_ccb->cont_info.curr_sdp_rec = NULL;
+                p_ccb->cont_info.prev_sdp_rec = NULL;
+            }
+            else
+            {
+                p_ccb->cont_info.curr_sdp_rec -= 1;
+                p_ccb->cont_info.prev_sdp_rec = p_ccb->cont_info.curr_sdp_rec -1;
+            }
+        }
+    }
+}
 
 /*******************************************************************************
 **
@@ -226,6 +261,8 @@
 *******************************************************************************/
 UINT8 *sdpu_build_attrib_entry (UINT8 *p_out, tSDP_ATTRIBUTE *p_attr)
 {
+    if(!p_out)
+        return p_out;
     /* First, store the attribute ID. Goes as a UINT */
     UINT8_TO_BE_STREAM  (p_out, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
     UINT16_TO_BE_STREAM (p_out, p_attr->id);
@@ -1044,10 +1081,13 @@
     }
 
     size_t len_to_copy = ((attr_len - *offset) < len) ? (attr_len - *offset) : len;
-    memcpy(p_out, &p_attr_buff[*offset], len_to_copy);
+    if(p_out)
+    {
+        memcpy(p_out, &p_attr_buff[*offset], len_to_copy);
 
-    p_out = &p_out[len_to_copy];
-    *offset += len_to_copy;
+        p_out = &p_out[len_to_copy];
+        *offset += len_to_copy;
+    }
 
     osi_free(p_attr_buff);
     return p_out;
diff --git a/stack/sdp/sdpint.h b/stack/sdp/sdpint.h
index b0548f5..4763e79 100644
--- a/stack/sdp/sdpint.h
+++ b/stack/sdp/sdpint.h
@@ -157,6 +157,7 @@
     UINT16            next_attr_index; /* attr index for next continuation response */
     UINT16            next_attr_start_id;  /* attr id to start with for the attr index in next cont. response */
     tSDP_RECORD       *prev_sdp_rec; /* last sdp record that was completely sent in the response */
+    tSDP_RECORD       *curr_sdp_rec; /* sdp record that is currently being sent in the response */
     BOOLEAN           last_attr_seq_desc_sent; /* whether attr seq length has been sent previously */
     UINT16            attr_offset; /* offset within the attr to keep trak of partial attributes in the responses */
 } tSDP_CONT_INFO;
@@ -274,6 +275,7 @@
 extern tCONN_CB *sdpu_find_ccb_by_db (tSDP_DISCOVERY_DB *p_db);
 extern tCONN_CB *sdpu_allocate_ccb (void);
 extern void      sdpu_release_ccb (tCONN_CB *p_ccb);
+extern void      sdpu_update_ccb_cont_info (UINT32 handle);
 
 extern UINT8    *sdpu_build_attrib_seq (UINT8 *p_out, UINT16 *p_attr, UINT16 num_attrs);
 extern UINT8    *sdpu_build_attrib_entry (UINT8 *p_out, tSDP_ATTRIBUTE *p_attr);
@@ -300,6 +302,11 @@
 extern tSDP_RECORD    *sdp_db_service_search (tSDP_RECORD *p_rec, tSDP_UUID_SEQ *p_seq);
 extern tSDP_RECORD    *sdp_db_find_record (UINT32 handle);
 extern tSDP_ATTRIBUTE *sdp_db_find_attr_in_rec (tSDP_RECORD *p_rec, UINT16 start_attr, UINT16 end_attr);
+extern BOOLEAN SDP_AddAttributetoRecord (tSDP_RECORD *p_rec, UINT16 attr_id, UINT8 attr_type,
+                                  UINT32 attr_len, UINT8 *p_val);
+extern BOOLEAN SDP_AddProfileDescriptorListtoRecord (tSDP_RECORD *p_rec, UINT16 profile_uuid,
+                                      UINT16 version);
+extern BOOLEAN SDP_DeleteAttributefromRecord (tSDP_RECORD *p_rec, UINT16 attr_id);
 
 
 /* Functions provided by sdp_server.c
@@ -310,6 +317,10 @@
 #define sdp_server_handle_client_req(p_ccb, p_msg)
 #endif
 
+extern BOOLEAN sdp_dev_blacklisted_for_avrcp15 (BD_ADDR addr);
+extern int sdp_get_stored_avrc_tg_version(BD_ADDR addr);
+
+
 /* Functions provided by sdp_discovery.c
 */
 #if SDP_CLIENT_ENABLED == TRUE
diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c
index a986cbd..00ae046 100644
--- a/stack/smp/smp_act.c
+++ b/stack/smp/smp_act.c
@@ -193,6 +193,8 @@
 
         if (callback_rc == SMP_SUCCESS)
         {
+            bt_bdaddr_t remote_bdaddr;
+            bdcpy(remote_bdaddr.address, p_cb->pairing_bda);
             switch (p_cb->cb_evt)
             {
                 case SMP_IO_CAP_REQ_EVT:
@@ -227,7 +229,7 @@
                     if (!(p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT)
                         || lmp_version_below(p_cb->pairing_bda, HCI_PROTO_VERSION_4_2)
                         || interop_match_addr(INTEROP_DISABLE_LE_SECURE_CONNECTIONS,
-                            (const bt_bdaddr_t *)&p_cb->pairing_bda))
+                            (const bt_bdaddr_t *)&remote_bdaddr))
                     {
                         p_cb->loc_auth_req &= ~SMP_KP_SUPPORT_BIT;
                         p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
@@ -244,13 +246,15 @@
                     p_cb->loc_enc_size = cb_data.io_req.max_key_size;
                     p_cb->local_i_key = cb_data.io_req.init_keys;
                     p_cb->local_r_key = cb_data.io_req.resp_keys;
+                    p_cb->loc_auth_req |= SMP_H7_SUPPORT_BIT;
 
                     p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
                     p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
 
                     SMP_TRACE_WARNING ( "for SMP over BR max_key_size: 0x%02x,\
-                        local_i_key: 0x%02x, local_r_key: 0x%02x",
-                        p_cb->loc_enc_size, p_cb->local_i_key, p_cb->local_r_key);
+                        local_i_key: 0x%02x, local_r_key: 0x%02x, auth_req = %d",
+                        p_cb->loc_enc_size, p_cb->local_i_key, p_cb->local_r_key, p_cb->loc_auth_req);
+
 
                     smp_br_state_machine_event(p_cb, SMP_BR_KEYS_RSP_EVT, NULL);
                     break;
@@ -956,6 +960,13 @@
         p_cb->local_r_key &= (SMP_SEC_KEY_TYPE_ID | SMP_SEC_KEY_TYPE_CSRK);
     }
 
+    /* Check if H7 function needs to be used for key derivation*/
+    if ((p_cb->loc_auth_req & SMP_H7_SUPPORT_BIT) && (p_cb->peer_auth_req & SMP_H7_SUPPORT_BIT))
+    {
+        p_cb->key_derivation_h7_used = TRUE;
+    }
+    SMP_TRACE_DEBUG("%s use h7 = %d", __func__, p_cb->key_derivation_h7_used);
+
     SMP_TRACE_DEBUG("%s rcvs upgrades: i_keys=0x%x r_keys=0x%x "
                       "(i-initiator r-responder)", __FUNCTION__, p_cb->local_i_key,
                       p_cb->local_r_key);
diff --git a/stack/smp/smp_cmac.c b/stack/smp/smp_cmac.c
index b164669..1989292 100644
--- a/stack/smp/smp_cmac.c
+++ b/stack/smp/smp_cmac.c
@@ -134,7 +134,7 @@
     tSMP_ENC output;
     UINT8    i = 1, err = 0;
     UINT8    x[16] = {0};
-    UINT8   *p_mac;
+    UINT8   *p_mac = NULL;
 
     SMP_TRACE_EVENT ("cmac_aes_k_calculate ");
 
@@ -154,6 +154,8 @@
 
     if (!err)
     {
+        if (tlen > BT_OCTET16_LEN)
+           tlen = BT_OCTET16_LEN;
         p_mac = output.param_buf + (BT_OCTET16_LEN - tlen);
         memcpy(p_signature, p_mac, tlen);
 
diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h
index aea8538..f11fe49 100644
--- a/stack/smp/smp_int.h
+++ b/stack/smp/smp_int.h
@@ -312,6 +312,7 @@
                                             /* either in Secure Connections mode or not at all */
     tSMP_ASSO_MODEL selected_association_model;
     BOOLEAN         le_secure_connections_mode_is_used;
+    BOOLEAN         key_derivation_h7_used;
     BOOLEAN le_sc_kp_notif_is_used;
     tSMP_SC_KEY_TYPE local_keypress_notification;
     tSMP_SC_KEY_TYPE peer_keypress_notification;
@@ -532,6 +533,7 @@
 extern BOOLEAN smp_calculate_f6(UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *r, UINT8 *iocap,
                                UINT8 *a1, UINT8 *a2, UINT8 *f3);
 extern BOOLEAN smp_calculate_h6(UINT8 *w, UINT8 *keyid, UINT8 *h2);
+extern BOOLEAN smp_calculate_h7(UINT8 *salt, UINT8 *w, UINT8 *h2);
 #if SMP_DEBUG == TRUE
 extern void smp_debug_print_nbyte_little_endian (UINT8 *p, const UINT8 *key_name,
                                                  UINT8 len);
diff --git a/stack/smp/smp_keys.c b/stack/smp/smp_keys.c
index a985f97..6860f95 100644
--- a/stack/smp/smp_keys.c
+++ b/stack/smp/smp_keys.c
@@ -1909,6 +1909,11 @@
     tBTM_SEC_DEV_REC *p_dev_rec;
     BD_ADDR bda_for_lk;
     tBLE_ADDR_TYPE conn_addr_type;
+    BT_OCTET16  salt = {
+        0x31, 0x70, 0x6D, 0x74, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+    };
+
 
     SMP_TRACE_DEBUG ("%s", __func__);
 
@@ -1937,7 +1942,11 @@
     BT_OCTET16 intermediate_link_key;
     BOOLEAN ret = TRUE;
 
-    ret = smp_calculate_h6(p_cb->ltk, (UINT8 *)"1pmt" /* reversed "tmp1" */,intermediate_link_key);
+    if (p_cb->key_derivation_h7_used)
+        ret = smp_calculate_h7((UINT8*)salt, p_cb->ltk, intermediate_link_key);
+    else
+        ret = smp_calculate_h6(p_cb->ltk, (UINT8 *)"1pmt" /* reversed "tmp1" */,intermediate_link_key);
+
     if (!ret)
     {
         SMP_TRACE_ERROR("%s failed to derive intermediate_link_key", __func__);
@@ -2011,6 +2020,10 @@
     BOOLEAN ret = TRUE;
     tBTM_SEC_DEV_REC *p_dev_rec;
     UINT8 rev_link_key[16];
+    BT_OCTET16  salt = {
+        0x32, 0x70, 0x6D, 0x74, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+    };
 
     SMP_TRACE_DEBUG ("%s", __FUNCTION__);
 
@@ -2043,9 +2056,17 @@
     REVERSE_ARRAY_TO_STREAM(p1, p2, 16);
 
     BT_OCTET16 intermediate_long_term_key;
-    /* "tmp2" obtained from the spec */
-    ret = smp_calculate_h6(rev_link_key, (UINT8 *) "2pmt" /* reversed "tmp2" */,
-                           intermediate_long_term_key);
+
+    if (p_cb->key_derivation_h7_used)
+    {
+        ret = smp_calculate_h7((UINT8*)salt, rev_link_key, intermediate_long_term_key);
+    }
+    else
+    {
+        /* "tmp2" obtained from the spec */
+        ret = smp_calculate_h6(rev_link_key, (UINT8 *) "2pmt" /* reversed "tmp2" */,
+                               intermediate_long_term_key);
+    }
 
     if (!ret)
     {
@@ -2145,6 +2166,78 @@
 
 /*******************************************************************************
 **
+** Function         smp_calculate_h7
+**
+** Description      The function calculates
+**                  C = h7(SALT, W) = AES-CMAC   (W)
+**                                            SALT
+**                  where
+**                  input:  W is 128 bit,
+**                          SALT is 128 bit,
+**                  output: C is 128 bit.
+**
+** Returns          FALSE if out of resources, TRUE in other cases.
+**
+** Note             The LSB is the first octet, the MSB is the last octet of
+**                  the AES-CMAC input/output stream.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_h7(UINT8 *salt, UINT8 *w, UINT8 *c)
+{
+#if SMP_DEBUG == TRUE
+    UINT8   *p_print = NULL;
+#endif
+
+    SMP_TRACE_DEBUG ("%s",__FUNCTION__);
+#if SMP_DEBUG == TRUE
+    p_print = w;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"W", BT_OCTET16_LEN);
+    p_print = salt;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"SALT", BT_OCTET16_LEN);
+#endif
+
+    UINT8 *p = NULL;
+    UINT8 key[BT_OCTET16_LEN];
+
+    p = key;
+    ARRAY_TO_STREAM(p, salt, BT_OCTET16_LEN);
+
+#if SMP_DEBUG == TRUE
+    p_print = key;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"K", BT_OCTET16_LEN);
+#endif
+
+    UINT8 msg_len = BT_OCTET16_LEN /* msg size */;
+    UINT8 msg[BT_OCTET16_LEN];
+
+    p = msg;
+    ARRAY_TO_STREAM(p, w, BT_OCTET16_LEN);
+
+#if SMP_DEBUG == TRUE
+    p_print = msg;
+    smp_debug_print_nbyte_little_endian (p_print,(const UINT8 *) "M", msg_len);
+#endif
+
+    BOOLEAN ret = TRUE;
+    UINT8 cmac[BT_OCTET16_LEN];
+    if (!aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac))
+    {
+        SMP_TRACE_ERROR("%s failed",__FUNCTION__);
+        ret = FALSE;
+    }
+
+#if SMP_DEBUG == TRUE
+    p_print = cmac;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"AES-CMAC", BT_OCTET16_LEN);
+#endif
+
+    p = c;
+    ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
+    return ret;
+}
+
+/*******************************************************************************
+**
 ** Function         smp_start_nonce_generation
 **
 ** Description      This function starts nonce generation.
diff --git a/stack/smp/smp_main.c b/stack/smp/smp_main.c
index 2727af8..09b3999 100644
--- a/stack/smp/smp_main.c
+++ b/stack/smp/smp_main.c
@@ -824,7 +824,7 @@
     /* execute action functions */
     for (i = 0; i < SMP_NUM_ACTIONS; i++)
     {
-        if ((action = state_table[entry-1][i]) != SMP_SM_NO_ACTION)
+        if ((action = state_table[entry-1][i]) < SMP_SM_NO_ACTION)
         {
             (*smp_sm_action[action])(p_cb, (tSMP_INT_DATA *)p_data);
         }
@@ -859,7 +859,7 @@
 {
     const char *p_str = smp_event_name[SMP_MAX_EVT];
 
-    if (event <= SMP_MAX_EVT)
+    if (event && event <= SMP_MAX_EVT)
     {
         p_str = smp_event_name[event- 1];
     }
diff --git a/stack/smp/smp_utils.c b/stack/smp/smp_utils.c
index 883e83b..e372689 100644
--- a/stack/smp/smp_utils.c
+++ b/stack/smp/smp_utils.c
@@ -1197,7 +1197,13 @@
         p_cb->le_secure_connections_mode_is_used = TRUE;
     }
 
-    SMP_TRACE_DEBUG("use_sc_process = %d", p_cb->le_secure_connections_mode_is_used);
+    if ((p_cb->peer_auth_req & SMP_H7_SUPPORT_BIT) && (p_cb->loc_auth_req & SMP_H7_SUPPORT_BIT))
+    {
+        p_cb->key_derivation_h7_used = TRUE;
+    }
+
+    SMP_TRACE_DEBUG("use_sc_process = %d, h7 use = %d", p_cb->le_secure_connections_mode_is_used,
+                     p_cb->key_derivation_h7_used);
 
     if (p_cb->le_secure_connections_mode_is_used)
     {
diff --git a/stack/srvc/srvc_battery.c b/stack/srvc/srvc_battery.c
index 90632df..a3ce3ae 100644
--- a/stack/srvc/srvc_battery.c
+++ b/stack/srvc/srvc_battery.c
@@ -203,7 +203,7 @@
     tBA_INST            *p_inst;
     tGATT_CHAR_PROP     prop = GATT_CHAR_PROP_BIT_READ;
 
-    if (battery_cb.inst_id == BA_MAX_INT_NUM)
+    if (battery_cb.inst_id >= BA_MAX_INT_NUM)
     {
         GATT_TRACE_ERROR("MAX battery service has been reached");
         return 0;
diff --git a/stack/srvc/srvc_eng.c b/stack/srvc/srvc_eng.c
index 92d1d6e..fd7eaf0 100644
--- a/stack/srvc/srvc_eng.c
+++ b/stack/srvc/srvc_eng.c
@@ -270,6 +270,11 @@
     tGATTS_RSP  rsp_msg ;
     UINT8       act = SRVC_ACT_IGNORE;
     UINT8   clcb_idx = srvc_eng_find_clcb_idx_by_conn_id(conn_id);
+    if( clcb_idx == SRVC_MAX_APPS)
+    {
+        GATT_TRACE_ERROR("srvc_eng_s_request_cback received for unknown connection");
+        return;
+    }
 
     GATT_TRACE_EVENT("srvc_eng_s_request_cback : recv type (0x%02x)", type);
 
diff --git a/test/blegatt_test/Android.mk b/test/blegatt_test/Android.mk
new file mode 100644
index 0000000..95b548b
--- /dev/null
+++ b/test/blegatt_test/Android.mk
@@ -0,0 +1,43 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+
+LOCAL_SRC_FILES:= gatt_test.c
+
+LOCAL_C_INCLUDES += . \
+         $(LOCAL_PATH)/../../stack/include \
+         $(LOCAL_PATH)/../../include \
+         $(LOCAL_PATH)/../../stack/l2cap \
+         $(LOCAL_PATH)/../../utils/include \
+         $(LOCAL_PATH)/../../ \
+         $(LOCAL_PATH)/btif/include \
+         $(LOCAL_PATH)/../../stack/gatt \
+         $(LOCAL_PATH)/../../stack/btm \
+         $(LOCAL_PATH)/../../stack/avdt \
+         $(LOCAL_PATH)/../../stack/btm \
+         $(LOCAL_PATH)/../../hcis \
+         $(LOCAL_PATH)/../../hci/include \
+         $(LOCAL_PATH)/../../bta/include \
+         $(LOCAL_PATH)/../../bta/sys \
+         $(LOCAL_PATH)/../../osi/include \
+         $(bluetooth_C_INCLUDES)
+
+LOCAL_CFLAGS += $(bluetooth_CFLAGS)
+LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS)
+LOCAL_CPPFLAGS += $(bluetooth_CPPFLAGS)
+LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
+LOCAL_MODULE_TAGS := debug optional
+LOCAL_MODULE:= gatt_test
+
+#LOCAL_LDLIBS +=  -ldl -llog
+#LIBS_c += -lreadline
+
+LOCAL_SHARED_LIBRARIES += libcutils   \
+                          libutils    \
+                          libhardware \
+                          libhardware_legacy
+
+LOCAL_MULTILIB := 32
+
+include $(BUILD_EXECUTABLE)
diff --git a/test/blegatt_test/README.txt b/test/blegatt_test/README.txt
new file mode 100644
index 0000000..1b4f478
--- /dev/null
+++ b/test/blegatt_test/README.txt
@@ -0,0 +1,191 @@
+Bluedroid LE Test Application
+==========================
+The test application provides a small console shell interface that allows
+access to the Bluetooth HAL API library though ASCII commands. This is similar
+to how the real JNI service would operate. The primary objective of this
+application is to allow Bluetooth to be put in DUT Mode for RF/BB BQB test purposes.
+
+This application is mutually exclusive with the Java based Bluetooth.apk. Hence
+before launching the application, it should be ensured that the Settings->Bluetooth is OFF.
+
+This application is built as 'bdt' and shall be available in '/system/bin/bdt'
+
+Limitations
+===========
+1.) Settings->Bluetooth must be OFF for this application to work
+2.) Currently, only the SIG 'HCI Test Mode' commands are supported. The vendor
+specific HCI test mode commands to be added.
+
+
+==================
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+proceduredure to create LE-L2CAP Connection Oriented Channal
+============================================================
+Step 1:
+        --> Run the gatt_testtool executable on both side (i.e, peripheral & central)
+
+Step 2:
+        Start Advertisement
+        ===================
+
+        > start_adv <uuid> <flag> ( peripheral side )
+
+        Where,
+                flag     -->    1 (start advertisement)
+                                 0 (stop advertisement)
+
+                option    -->    1 (Doing registration with only Gatt_cb which is required for LE-L2CAP)
+                                 0 (Doing the existing s_registration for gatt_testtool)
+
+        This will start the advertisement and listen for the incoming LE connection.
+
+Step 3:
+        Start&Stop scanning
+        ===================
+
+        > c_scan_start  ( central side )
+        > c_scan_stop ( stop it as and when we find the remote device) ( Central side)
+
+Step 4:
+       listen for incoming LE COC
+       ==========================
+
+        > le_l2cap_listen  <le_psm> <mtu> <mps> <init_credits> <sec_level> ( peripheral side )
+
+        Where,
+                le_psm          -->     1 to 127 (Fixed Range, SIG assigned)
+                                        128 to 255 (Dynamic Range)
+                mtu             -->     23 to 65535
+                mps             -->     23 to 65533
+                init_credits    -->     0 to 65535
+                sec_level       -->     0 for no security
+                                        1 for authentication
+                                -->     2 for encryption
+
+        Example : le_l2cap_listen 128 23 23 100 0
+        Note : MTU value should not be less then MPS
+
+Step 5:
+        Initiate LE COC connection
+        ==========================
+
+        > le_l2cap_coc_connect  <le_psm> <mtu> <mps> <init_credits> <sec_level> <bd_addr> ( central side)
+
+        Where,
+                le_psm          -->     1 to 127 (Fixed Range, SIG assigned)
+                                        128 to 255 (Dynamic Range)
+                mtu             -->     23 to 65535
+                mps             -->     23 to 65533
+                init_credits    -->     0 to 65535
+                bd_addr         -->     remote BD address
+                sec_level       -->     0 for no security
+                                        1 for authentication
+                                -->     2 for encryption
+
+        Example :  le_l2cap_coc_connect 128 23 23 100 0 7e58587530b8
+        Note : MTU value should not be less then MPS
+
+Step 6:
+        Send Credits [LE Credit Based Flow Control Mode]
+        ================================================
+
+        [Initiating the LE credit based flow control with the no.of credits incase of initial credits were
+         not provided i.e set as 0 as part of connection establishment, this command will be ignored
+         if the intial credits were given as part of conneciton establishment.]
+
+        > le_l2cap_coc_flow_ctrl <cid> <credits>
+
+        Where,
+                cid             -->     64 to 127 (Dynamic Range)
+                                        [ Use the allocated CID during LE COC connection initialization]
+                credits         -->     1 to 65535
+
+        Note : When we plan to send this command, the initial credit value has to be set with zero
+               during the initialization LE COC connection.
+
+Step 7:
+        Send file
+        =========
+
+        push the file in to the device "/system" directory which you want to sent.
+
+        > send_file <cid> < file_path >
+
+        Where,
+                cid             -->     64 to 127 (Dynamic Range)
+                                        [ Use the allocated CID during LE COC connection initialization]
+                file_path       -->     give the file path which is going to be sent.
+
+        Example : send_file 65 /system/bt_stack_file.txt
+
+Step 8:
+        Disconnect LE COC
+        =================
+
+        > le_coc_disconnect <cid>
+
+        Where,
+                cid             -->     64 to 127 (Dynamic Range)
+                                        [ Use the allocated CID during LE COC connection initialization]
+
diff --git a/test/blegatt_test/gatt_test.c b/test/blegatt_test/gatt_test.c
new file mode 100644
index 0000000..982c80c
--- /dev/null
+++ b/test/blegatt_test/gatt_test.c
@@ -0,0 +1,3010 @@
+/******************************************************************************
+ ** Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ *
+ *  Not a Contribution.
+ *
+ *  Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+
+/************************************************************************************
+ *
+ *  Filename:      gatt_tool.c
+ *
+ *  Description:   Bluedroid GATT TOOL application
+ *
+ ***********************************************************************************/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/prctl.h>
+#include <sys/capability.h>
+//#include <sys/time.h>
+//#include <signal.h>
+//#include <time.h>
+#include "bt_target.h"
+#include "l2c_api.h"
+#include "bta_api.h"
+#include "l2c_int.h"
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <private/android_filesystem_config.h>
+#include <android/log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/bluetooth.h>
+#include <hardware/bt_gatt.h>
+#include <hardware/bt_gatt_client.h>
+#include <hardware/bt_gatt_server.h>
+#include <hardware/bt_gatt_types.h>
+//#include "../../osi/include/allocator.h"
+#include <bt_testapp.h>
+
+#include <signal.h>
+#include <time.h>
+
+
+#ifdef TEST_APP_INTERFACE
+/************************************************************************************
+**  Constants & Macros
+************************************************************************************/
+
+#ifndef TRUE
+#define     TRUE       1
+#endif
+#ifndef FALSE
+#define     FALSE      0
+#endif
+
+#define PID_FILE "/data/.bdt_pid"
+
+#ifndef MAX
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+#endif
+
+#define CASE_RETURN_STR(const) case const: return #const;
+
+/************************************************************************************
+**  Local type definitions
+************************************************************************************/
+static void register_client_cb(int status, int client_if, bt_uuid_t *app_uuid);
+static void scan_result_cb(bt_bdaddr_t* remote_bd_addr, int rssi, uint8_t* adv_data);
+static void listen_cb(int status, int server_if);
+
+static void register_server_cb(int status, int server_if, bt_uuid_t *app_uuid);
+
+
+/************************************************************************************
+**  Static variables
+************************************************************************************/
+
+static unsigned char main_done = 0;
+static bt_status_t status;
+typedef struct
+{
+    UINT16      result;                 /* Only used in confirm messages */
+    UINT16      credits;                /* used to send the outstanding credits */
+    UINT16      le_psm;
+    UINT16      le_mps;
+    UINT16      le_mtu;
+    UINT16      init_credits;          /* initial credits */
+} tL2CAP_LE_CONN_INFO;
+
+typedef struct
+{
+    BOOLEAN                 in_use;
+    UINT16                  psm;
+    UINT16                  lcid;
+    tL2CAP_LE_CONN_INFO     loc_conn_info;
+    tL2CAP_LE_CONN_INFO     rmt_conn_info;
+    BOOLEAN                 is_server;
+} t_le_chnl_info;
+
+t_le_chnl_info le_chnl_conn_info[MAX_L2CAP_CLIENTS];
+#define LE_ACL_MAX_BUFF_SIZE 4096
+static int num_frames = 1;
+static unsigned long g_delay = 1; /* Default delay before data transfer */
+static int count = 1;
+static UINT16 g_BleEncKeySize = 16;
+//static int g_omps = 0;
+//static int rcv_count = 0;
+static int g_le_coc_if = 0;
+static int rcv_itration = 0;
+static volatile BOOLEAN cong_status = FALSE;
+/* Control channel LE-L2CAP default options */
+static tL2CAP_LE_CONN_INFO le_conn_info;
+static tL2CAP_LE_CFG_INFO local_coc_cfg;
+
+/* Main API */
+static bluetooth_device_t* bt_device;
+
+const bt_interface_t* sBtInterface = NULL;
+
+static gid_t groups[] = { AID_NET_BT, AID_INET, AID_NET_BT_ADMIN,
+                          AID_SYSTEM, AID_MISC, AID_SDCARD_RW,
+                          AID_NET_ADMIN, AID_VPN};
+
+enum {
+    DISCONNECT,
+    CONNECTING,
+    CONNECTED,
+    DISCONNECTING
+};
+static unsigned char bt_enabled = 0;
+static int  g_ConnectionState   = DISCONNECT;
+static int  g_AdapterState      = BT_STATE_OFF;
+static int  g_PairState         = BT_BOND_STATE_NONE;
+
+
+static int  g_conn_id        = 0;
+static int  g_client_if      = 0;
+static int  g_server_if      = 0;
+static int  g_client_if_scan = 0;
+static int  g_server_if_scan = 0;
+
+const btgatt_test_interface_t     *sGattInterface = NULL;
+const  btgatt_interface_t   *sGattIfaceScan = NULL;
+const btsmp_interface_t    *sSmpIface             = NULL;
+const btgap_interface_t    *sGapInterface         = NULL;
+const btl2cap_interface_t *sL2capInterface = NULL;
+
+
+int  Btif_gatt_layer = TRUE;
+bt_bdaddr_t *remote_bd_address;
+
+static UINT16 g_SecLevel = 0;
+static BOOLEAN g_ConnType = TRUE;//DUT is initiating connection
+static BOOLEAN g_Fcr_Present = FALSE;
+static UINT8 g_Fcr_Mode = L2CAP_FCR_BASIC_MODE;
+static UINT8 g_Ertm_AllowedMode = (L2CAP_FCR_CHAN_OPT_BASIC | L2CAP_FCR_CHAN_OPT_ERTM | L2CAP_FCR_CHAN_OPT_STREAM);
+
+
+/* Default mtu */
+static int g_imtu = 672;
+static int g_omtu = 0;
+
+enum {
+L2CAP_NOT_CONNECTED,
+L2CAP_CONN_SETUP,
+L2CAP_CONNECTED
+};
+
+//static int L2cap_conn_state = L2CAP_NOT_CONNECTED;
+static tL2CAP_CFG_INFO tl2cap_cfg_info;
+static long data_size = -1;
+static UINT16           g_PSM           = 0;
+static UINT16           g_lcid          = 0;
+
+
+enum {
+    SEND,
+    RECEIVE,
+    WAITANDSEND,
+    PAIR,
+    PING,
+    CONNECT,
+};
+
+
+/* Control channel eL2CAP default options */
+tL2CAP_FCR_OPTS ertm_fcr_opts_def = {
+    L2CAP_FCR_ERTM_MODE,
+    3, /* Tx window size */
+    MCA_FCR_OPT_MAX_TX_B4_DISCNT, /* Maximum transmissions before disconnecting */
+    2000, /* Retransmission timeout (2 secs) */
+    MCA_FCR_OPT_MONITOR_TOUT, /* Monitor timeout (12 secs) */
+    100 /* MPS segment size */
+};
+
+tL2CAP_FCR_OPTS stream_fcr_opts_def = {
+    L2CAP_FCR_STREAM_MODE,
+    3,/* Tx window size */
+    MCA_FCR_OPT_MAX_TX_B4_DISCNT, /* Maximum transmissions before disconnecting */
+    2000, /* Retransmission timeout (2 secs) */
+    MCA_FCR_OPT_MONITOR_TOUT, /* Monitor timeout (12 secs) */
+    100 /* MPS segment size */
+};
+static tL2CAP_ERTM_INFO t_ertm_info = {0, 0, 0, 0, 0, 0};
+
+
+/************************************************************************************
+**  Static functions
+************************************************************************************/
+
+static void process_cmd(char *p, unsigned char is_job);
+//static void job_handler(void *param);
+static void bdt_log(const char *fmt_str, ...);
+static void l2c_connect(bt_bdaddr_t *bd_addr);
+static UINT16 do_l2cap_connect(bt_bdaddr_t * bd_addr);
+
+
+
+int GetBdAddr(char *p, bt_bdaddr_t *pbd_addr);
+
+/* LE L2CAP functions */
+static t_le_chnl_info *le_allocate_conn_info(UINT16 psm, BOOLEAN is_server);
+static t_le_chnl_info *le_get_conn_info(UINT16 psm, BOOLEAN is_server);
+static t_le_chnl_info *le_get_conn_info_by_lcid(UINT16 lcid);
+static BOOLEAN le_release_conn_info(t_le_chnl_info *le_conn_info);
+UINT8 do_l2cap_DataWrite(UINT16 chnl_id, char *p , UINT32 len);
+static int Send_Data();
+static int send_file(char *p);
+static void le_l2cap_coc_connect(char *svr);
+UINT16 do_le_l2cap_coc_connect(char *p);
+static void le_l2cap_coc_flow_ctrl(char *p);
+UINT16 do_le_l2cap_coc_flow_ctrl(char *p);
+static void do_le_coc_disconnect(char *p);
+int GetFileName(char *p, char *filename);
+
+/************************************************************************************
+**  GATT Client Callbacks
+************************************************************************************/
+static void register_client_cb(int status, int client_if, bt_uuid_t *app_uuid)
+{
+    printf("%s:: status=%d, client_if=%d, uuid=%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x \n", __FUNCTION__, status, client_if,
+            app_uuid->uu[0], app_uuid->uu[1], app_uuid->uu[2], app_uuid->uu[3],
+            app_uuid->uu[4], app_uuid->uu[5], app_uuid->uu[6], app_uuid->uu[7],
+            app_uuid->uu[8], app_uuid->uu[9], app_uuid->uu[10], app_uuid->uu[11],
+            app_uuid->uu[12], app_uuid->uu[13], app_uuid->uu[14], app_uuid->uu[15]);
+    if(0 == status)    g_client_if_scan = client_if;
+}
+
+static void scan_result_cb(bt_bdaddr_t* remote_bd_addr, int rssi, uint8_t* adv_data)
+{
+    printf("%s:: remote_bd_addr= %02X%02X%02X%02X%02X%02X , adv_data=0x%x \n",  __FUNCTION__,
+    remote_bd_addr->address[0], remote_bd_addr->address[1], remote_bd_addr->address[2],
+    remote_bd_addr->address[3], remote_bd_addr->address[4], remote_bd_addr->address[5], *adv_data);
+}
+
+static void connect_cb(int conn_id, int status, int client_if, bt_bdaddr_t* remote_bd_addr)
+{
+    printf("%s:: remote_bd_addr=%02x:%02x:%02x:%02x:%02x:%02x, conn_id=0x%x, status=%d, client_if=%d\n",  __FUNCTION__,
+    remote_bd_addr->address[0], remote_bd_addr->address[1], remote_bd_addr->address[2],
+    remote_bd_addr->address[3], remote_bd_addr->address[4], remote_bd_addr->address[5], conn_id, status, client_if);
+
+    g_conn_id = conn_id;
+    sGapInterface->Gap_BleAttrDBUpdate(remote_bd_addr->address, 50, 70, 0, 1000);
+
+}
+
+/*
+static void register_for_notification_cb(int conn_id, int registered, int status, btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
+{
+    printf("%s:: conn_id=%d, registered=%d, status=%d \n", __FUNCTION__, conn_id, registered, status);
+}
+*/
+
+static void listen_cb(int status, int server_if)
+{
+    printf("%s:: status=%d, server_if=%d \n", __FUNCTION__, status, server_if);
+    if(0 == status)    g_server_if = server_if;
+}
+
+static btgatt_client_callbacks_t sGattClient_cb =
+{
+    register_client_cb,
+    scan_result_cb,
+    connect_cb,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL, //register_for_notification_cb,
+    NULL,
+    NULL,
+    NULL,
+    listen_cb,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+
+/************************************************************************************
+**  GATT Server Callbacks
+************************************************************************************/
+static void register_server_cb(int status, int server_if, bt_uuid_t *app_uuid)
+{
+    printf("%s:: status=%d, server_if=%d \n", __FUNCTION__, status, server_if);
+    if(0 == status)    g_server_if_scan = server_if;
+}
+
+static void server_connection_cb(int conn_id, int server_if, int connected, bt_bdaddr_t *bda)
+{
+    printf("%s:: conn_id=%d, server_if=%d \n", __FUNCTION__, conn_id, server_if);
+    g_conn_id = conn_id;
+}
+
+static btgatt_server_callbacks_t     sGattServer_cb =
+{
+    register_server_cb,
+    server_connection_cb, //connection_callback             connection_cb;
+    NULL, //service_added_callback          service_added_cb;
+    NULL, //included_service_added_callback included_service_added_cb;
+    NULL, //characteristic_added_callback   characteristic_added_cb;
+    NULL, //descriptor_added_callback       descriptor_added_cb;
+    NULL, //service_started_callback        service_started_cb;
+    NULL, //service_stopped_callback        service_stopped_cb;
+    NULL, //service_deleted_callback        service_deleted_cb;
+    NULL, //request_read_callback           request_read_cb;
+    NULL, //request_write_callback          request_write_cb;
+    NULL, //request_exec_write_callback     request_exec_write_cb;
+    NULL, //response_confirmation_callback  response_confirmation_cb;
+    NULL,
+    NULL,
+    NULL
+};
+
+
+/************************************************************************************
+**  GATT Callbacks
+************************************************************************************/
+static void DiscoverRes_cb (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data)
+{
+    printf("%s:: conn_id=%d, disc_type=%d\n", __FUNCTION__, conn_id, disc_type);
+}
+
+static void DiscoverCmpl_cb (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status)
+{
+    printf("%s:: conn_id=%d, disc_type=%d, status=%d\n", __FUNCTION__, conn_id, disc_type, status);
+}
+
+static void  OperationCmpl_cb(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data)
+{
+    printf("%s:: conn_id=%d, op=%d, status=%d\n", __FUNCTION__, conn_id, op, status);
+}
+
+static void Connection_cb (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected, tGATT_DISCONN_REASON reason,tBT_TRANSPORT transport)
+{
+    printf("%s:: remote_bd_addr=%02x:%02x:%02x:%02x:%02x:%02x, conn_id=0x%x, connected=%d, reason=%d, gatt_if=%d \n", __FUNCTION__,
+            bda[0], bda[1], bda[2], bda[3], bda[4], bda[5],
+            conn_id, connected, reason, gatt_if);
+    g_conn_id = conn_id;
+}
+
+static void AttributeReq_cb(UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE type, tGATTS_DATA *p_data)
+{
+    printf("%s:: conn_id=%d, trans_id=%d, type=%u\n", __FUNCTION__, conn_id, trans_id, type);
+}
+
+
+static tGATT_CBACK sGattCB =
+{
+    Connection_cb,
+    OperationCmpl_cb,
+    DiscoverRes_cb,
+    DiscoverCmpl_cb,
+    AttributeReq_cb,
+    NULL,
+    NULL
+};
+
+/************************************************************************************
+**  GAP Callbacks
+************************************************************************************/
+/*
+static void gap_ble_s_attr_request_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE op_code, tGATTS_DATA *p_data)
+{
+    printf("%s:: conn_id=%d, trans_id=%d, op_code=%u\n", __FUNCTION__, conn_id, trans_id, op_code);
+}
+
+// client connection callback
+
+static void  gap_ble_c_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected, tGATT_DISCONN_REASON reason,tBT_TRANSPORT transport)
+{
+    printf("%s:: gatt_if=%d, remote_bd_addr=%02x:%02x:%02x:%02x:%02x:%02x, conn_id=%d, connected=%d, reason=%d\n", __FUNCTION__,
+    gatt_if, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5], conn_id, connected, reason);
+    g_conn_id = conn_id;
+}
+
+static void  gap_ble_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data)
+{
+    printf("%s:: conn_id=%d, op=%d, status=%d\n", __FUNCTION__, conn_id, op, status);
+}
+
+
+static tGATT_CBACK gap_cback =
+{
+    gap_ble_c_connect_cback,
+    gap_ble_c_cmpl_cback,
+    NULL,
+    NULL,
+    gap_ble_s_attr_request_cback,
+    NULL,
+    NULL
+};
+*/
+
+
+/************************************************************************************
+**  SMP Callbacks
+************************************************************************************/
+static UINT8 SMP_cb (tSMP_EVT event, BD_ADDR bda, tSMP_EVT_DATA *p_data)
+{
+    printf("%s:: event=%d(1-SMP_IO_CAP_REQ_EVT, 2-SMP_SEC_REQUEST_EVT,    \
+                   3-SMP_PASSKEY_NOTIF_EVT, 4-SMP_PASSKEY_REQ_EVT, 6-SMP_COMPLT_EVT),   \
+                  \nremote_bd_addr=%02x:%02x:%02x:%02x:%02x:%02x, PassKey=%u \n", __FUNCTION__, event,
+            bda[0], bda[1], bda[2], bda[3], bda[4], bda[5], p_data->passkey);
+    switch(event)
+    {
+    case SMP_IO_CAP_REQ_EVT:
+        printf("Io_Caps=%d, auth_req=%d, max_key_size=%d, init_keys=%d, resp_keys=%d \n", p_data->io_req.io_cap, p_data->io_req.auth_req, p_data->io_req.max_key_size, p_data->io_req.init_keys, p_data->io_req.resp_keys);
+        break;
+
+    case SMP_PASSKEY_REQ_EVT:
+    case SMP_PASSKEY_NOTIF_EVT:
+        printf("passkey value=%u\n", p_data->passkey);
+        sSmpIface->PasskeyReply(bda, SMP_SUCCESS, p_data->passkey);
+        break;
+    case SMP_OOB_REQ_EVT:
+        //p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED;
+        break;
+    case SMP_SEC_REQUEST_EVT:
+    case SMP_COMPLT_EVT:
+        printf("SMP Complete Event:: Reason=%d \n", p_data->cmplt.reason);
+        if(p_data->cmplt.reason == SMP_SUCCESS)
+        {
+            sSmpIface->SecurityGrant(bda, p_data->cmplt.reason);
+            printf("Granting Security \n");
+        }
+        break;
+    }
+    return 0;
+}
+
+
+
+
+/************************************************************************************
+**  Shutdown helper functions
+************************************************************************************/
+
+static void bdt_shutdown(void)
+{
+    bdt_log("shutdown bdroid test app\n");
+    main_done = 1;
+}
+
+
+/*****************************************************************************
+** Android's init.rc does not yet support applying linux capabilities
+*****************************************************************************/
+
+static void config_permissions(void)
+{
+    struct __user_cap_header_struct header;
+    struct __user_cap_data_struct cap[2];
+
+    bdt_log("set_aid_and_cap : pid %d, uid %d gid %d", getpid(), getuid(), getgid());
+
+    header.pid = 0;
+
+    prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+
+    setuid(AID_BLUETOOTH);
+    setgid(AID_BLUETOOTH);
+
+    header.version = _LINUX_CAPABILITY_VERSION_3;
+
+    cap[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW);
+    cap[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN);
+    cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].permitted |= CAP_TO_MASK(CAP_NET_BIND_SERVICE);
+    cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].permitted |= CAP_TO_MASK(CAP_SYS_RAWIO);
+    cap[CAP_TO_INDEX(CAP_SYS_NICE)].permitted |= CAP_TO_MASK(CAP_SYS_NICE);
+    cap[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
+    cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].permitted |= CAP_TO_MASK(CAP_WAKE_ALARM);
+
+    cap[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW);
+    cap[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN);
+    cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].effective |= CAP_TO_MASK(CAP_NET_BIND_SERVICE);
+    cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].effective |= CAP_TO_MASK(CAP_SYS_RAWIO);
+    cap[CAP_TO_INDEX(CAP_SYS_NICE)].effective |= CAP_TO_MASK(CAP_SYS_NICE);
+    cap[CAP_TO_INDEX(CAP_SETGID)].effective |= CAP_TO_MASK(CAP_SETGID);
+    cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].effective |= CAP_TO_MASK(CAP_WAKE_ALARM);
+
+    capset(&header, &cap[0]);
+    setgroups(sizeof(groups)/sizeof(groups[0]), groups);
+}
+
+
+
+/*****************************************************************************
+**   Logger API
+*****************************************************************************/
+
+void bdt_log(const char *fmt_str, ...)
+{
+    static char buffer[1024];
+    va_list ap;
+
+    va_start(ap, fmt_str);
+    vsnprintf(buffer, 1024, fmt_str, ap);
+    va_end(ap);
+
+    fprintf(stdout, "%s\n", buffer);
+}
+
+/*******************************************************************************
+ ** Misc helper functions
+ *******************************************************************************/
+static const char* dump_bt_status(bt_status_t status)
+{
+    switch(status)
+    {
+        CASE_RETURN_STR(BT_STATUS_SUCCESS)
+        CASE_RETURN_STR(BT_STATUS_FAIL)
+        CASE_RETURN_STR(BT_STATUS_NOT_READY)
+        CASE_RETURN_STR(BT_STATUS_NOMEM)
+        CASE_RETURN_STR(BT_STATUS_BUSY)
+        CASE_RETURN_STR(BT_STATUS_UNSUPPORTED)
+
+        default:
+            return "unknown status code";
+    }
+}
+
+/*
+static void hex_dump(char *msg, void *data, int size, int trunc)
+{
+    unsigned char *p = data;
+    unsigned char c;
+    int n;
+    char bytestr[4] = {0};
+    char addrstr[10] = {0};
+    char hexstr[ 16*3 + 5] = {0};
+    char charstr[16*1 + 5] = {0};
+
+    bdt_log("%s  \n", msg);
+
+    // truncate
+    if(trunc && (size>32))
+        size = 32;
+
+    for(n=1;n<=size;n++) {
+        if (n%16 == 1) {
+            // store address for this line
+            snprintf(addrstr, sizeof(addrstr), "%.4x",
+               ((intptr_t)p-(intptr_t)data) );
+        }
+
+        c = *p;
+        if (isalnum(c) == 0) {
+            c = '.';
+        }
+
+        // store hex str (for left side)
+        snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
+        strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
+
+        // store char str (for right side)
+        snprintf(bytestr, sizeof(bytestr), "%c", c);
+        strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
+
+        if(n%16 == 0) {
+            // line completed
+            bdt_log("[%4.4s]   %-50.50s  %s\n", addrstr, hexstr, charstr);
+            hexstr[0] = 0;
+            charstr[0] = 0;
+        } else if(n%8 == 0) {
+            // half line: add whitespaces
+            strncat(hexstr, "  ", sizeof(hexstr)-strlen(hexstr)-1);
+            strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1);
+        }
+        p++; // next byte
+    }
+
+    if (strlen(hexstr) > 0) {
+        // print rest of buffer if not empty
+        bdt_log("[%4.4s]   %-50.50s  %s\n", addrstr, hexstr, charstr);
+    }
+}
+*/
+
+/*******************************************************************************
+ ** Console helper functions
+ *******************************************************************************/
+
+void skip_blanks(char **p)
+{
+    while (**p == ' ')
+    (*p)++;
+}
+
+uint32_t get_int(char **p, int DefaultValue)
+{
+    uint32_t Value = 0;
+    unsigned char   UseDefault;
+
+    UseDefault = 1;
+    skip_blanks(p);
+
+    while ( ((**p)<= '9' && (**p)>= '0') )
+    {
+        Value = Value * 10 + (**p) - '0';
+        UseDefault = 0;
+        (*p)++;
+    }
+   if (UseDefault)
+       return DefaultValue;
+   else
+       return Value;
+}
+
+int get_signed_int(char **p, int DefaultValue)
+{
+    int    Value = 0;
+    unsigned char   UseDefault;
+    unsigned char  NegativeNum = 0;
+
+    UseDefault = 1;
+    skip_blanks(p);
+
+    if ((**p) == '-')
+    {
+        NegativeNum = 1;
+        (*p)++;
+    }
+    while ( ((**p)<= '9' && (**p)>= '0') )
+    {
+        Value = Value * 10 + (**p) - '0';
+        UseDefault = 0;
+        (*p)++;
+    }
+
+    if (UseDefault)
+        return DefaultValue;
+    else
+        return ((NegativeNum == 0)? Value : -Value);
+}
+
+void get_str(char **p, char *Buffer)
+{
+    skip_blanks(p);
+    while (**p != 0 && **p != ' ')
+    {
+        *Buffer = **p;
+        (*p)++;
+        Buffer++;
+    }
+
+    *Buffer = 0;
+}
+
+uint32_t get_hex_any(char **p, int DefaultValue, unsigned int NumOfNibble)
+{
+    uint32_t Value = 0;
+    unsigned char   UseDefault;
+
+    UseDefault = 1;
+    skip_blanks(p);
+
+    while ((NumOfNibble) && (((**p)<= '9' && (**p)>= '0') ||
+          ((**p)<= 'f' && (**p)>= 'a') ||
+          ((**p)<= 'F' && (**p)>= 'A')) )
+    {
+        if (**p >= 'a')
+            Value = Value * 16 + (**p) - 'a' + 10;
+        else if (**p >= 'A')
+            Value = Value * 16 + (**p) - 'A' + 10;
+        else
+        Value = Value * 16 + (**p) - '0';
+        UseDefault = 0;
+        (*p)++;
+        NumOfNibble--;
+    }
+
+    if (UseDefault)
+        return DefaultValue;
+    else
+        return Value;
+}
+uint32_t get_hex(char **p, int DefaultValue)
+{
+    return (get_hex_any(p, DefaultValue, 8));
+}
+uint32_t get_hex_byte(char **p, int DefaultValue)
+{
+    return (get_hex_any(p, DefaultValue, 2));
+}
+
+void get_bdaddr(const char *str, bt_bdaddr_t *bd) {
+    char *d = ((char *)bd), *endp;
+    int i;
+    for(i = 0; i < 6; i++) {
+        *d++ = strtol(str, &endp, 16);
+        if (*endp != ':' && i != 5) {
+            memset(bd, 0, sizeof(bt_bdaddr_t));
+            return;
+        }
+        str = endp + 1;
+    }
+}
+
+#define is_cmd(str) ((strlen(str) == strlen(cmd)) && strncmp((const char *)&cmd, str, strlen(str)) == 0)
+#define if_cmd(str)  if (is_cmd(str))
+
+typedef void (t_console_cmd_handler) (char *p);
+
+typedef struct {
+    const char *name;
+    t_console_cmd_handler *handler;
+    const char *help;
+    unsigned char is_job;
+} t_cmd;
+
+
+const t_cmd console_cmd_list[];
+static int console_cmd_maxlen = 0;
+
+static void cmdjob_handler(void *param)
+{
+    char *job_cmd = (char*)param;
+
+    bdt_log("cmdjob starting (%s)", job_cmd);
+
+    process_cmd(job_cmd, 1);
+
+    bdt_log("cmdjob terminating");
+
+    free(job_cmd);
+}
+
+static int create_cmdjob(char *cmd)
+{
+    pthread_t thread_id;
+    char *job_cmd;
+
+    job_cmd = (char*)calloc(1, strlen(cmd)+1); /* freed in job handler */
+    if (job_cmd) {
+       strlcpy(job_cmd, cmd,(strlen(cmd)+1));
+      if (pthread_create(&thread_id, NULL,
+                       (void*)cmdjob_handler, (void*)job_cmd)!=0)
+         perror("pthread_create");
+      return 0;
+    }
+    else
+       perror("create_Cmdjob malloc failed ");
+    return -1;
+}
+
+/*******************************************************************************
+ ** Load stack lib
+ *******************************************************************************/
+
+int HAL_load(void)
+{
+    int err = 0;
+
+    hw_module_t* module;
+    hw_device_t* device;
+
+    bdt_log("Loading HAL lib + extensions");
+
+    err = hw_get_module(BT_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
+    if (err == 0)
+    {
+
+        err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
+        bdt_log("HAL library open (%s)", strerror(err));
+        if (err == 0) {
+            bt_device = (bluetooth_device_t *)device;
+            sBtInterface = bt_device->get_bluetooth_interface();
+        }
+    }
+
+    bdt_log("HAL library loaded (%s) interface pointer =%x ", strerror(err), sBtInterface);
+
+    return err;
+}
+
+int HAL_unload(void)
+{
+    int err = 0;
+
+    bdt_log("Unloading HAL lib");
+
+    sBtInterface = NULL;
+
+    bdt_log("HAL library unloaded (%s)", strerror(err));
+
+    return err;
+}
+
+/*******************************************************************************
+ ** HAL test functions & callbacks
+ *******************************************************************************/
+
+void setup_test_env(void)
+{
+    int i = 0;
+
+    while (console_cmd_list[i].name != NULL)
+    {
+        console_cmd_maxlen = MAX(console_cmd_maxlen, (int)strlen(console_cmd_list[i].name));
+        i++;
+    }
+}
+
+void check_return_status(bt_status_t status)
+{
+    if (status != BT_STATUS_SUCCESS)
+    {
+        bdt_log("HAL REQUEST FAILED status : %d (%s)", status, dump_bt_status(status));
+    }
+    else
+    {
+        bdt_log("HAL REQUEST SUCCESS");
+    }
+}
+/*
+static void do_set_adv_params(char *p)
+{
+    bt_bdaddr_t bd_addr = {{0}};
+    int int_min = 0x0, int_max = 0x0, addr_type = 0;
+    int_max = get_int(&p, -1);
+    int_min = get_int(&p, -1);
+    if(int_max < int_min)
+        return;
+//    if(FALSE == GetBdAddr(p, &bd_addr))    return;
+//    sBtInterface->le_set_adv_params(int_min, int_max, &bd_addr, addr_type);
+}
+*/
+
+static void do_set_localname(char *p)
+{
+    printf("set name in progress: %s\n", p);
+    bt_property_t property = {BT_PROPERTY_BDNAME, strlen(p), p};
+    status = sBtInterface->set_adapter_property(&property);
+}
+
+static void adapter_state_changed(bt_state_t state)
+{
+    int V1 = 1000, V2=2;
+    bt_property_t property = {9 /*BT_PROPERTY_DISCOVERY_TIMEOUT*/, 4, &V1};
+    bt_property_t property1 = {7 /*SCAN*/, 2, &V2};
+    bt_property_t property2 ={1,9,"GATTTOOL"};
+    printf("ADAPTER STATE UPDATED : %s\n", (state == BT_STATE_OFF)?"OFF":"ON");
+
+    g_AdapterState = state;
+
+    if (state == BT_STATE_ON) {
+        bt_enabled = 1;
+        status = sBtInterface->set_adapter_property(&property1);
+        status = sBtInterface->set_adapter_property(&property);
+        status = sBtInterface->set_adapter_property(&property2);
+    } else {
+        bt_enabled = 0;
+    }
+}
+
+static void adapter_properties_changed(bt_status_t status, int num_properties, bt_property_t *properties)
+{
+ char Bd_addr[15] = {0};
+    if(NULL == properties)
+    {
+        printf("properties is null\n");
+        return;
+    }
+    switch(properties->type)
+    {
+    case BT_PROPERTY_BDADDR:
+        memcpy(Bd_addr, properties->val, properties->len);
+        break;
+//    case BT_PROPERTY_ADAPTER_BLE_ADV_MODE:
+ //       printf("Set in advertisement mode\n");
+ //       break;
+    default:
+        printf("property type not used\n");
+    }
+    return;
+}
+
+static void discovery_state_changed(bt_discovery_state_t state)
+{
+    printf("Discovery State Updated : %s\n", (state == BT_DISCOVERY_STOPPED)?"STOPPED":"STARTED");
+}
+
+
+static void pin_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name, uint32_t cod, bool min_16_digit )
+{
+    remote_bd_address = remote_bd_addr;
+    //bt_pin_code_t pincode = {{0x31, 0x32, 0x33, 0x34}};
+    printf("Enter the pin key displayed in the remote device and terminate the key entry with .\n");
+
+    /*if(BT_STATUS_SUCCESS != sBtInterface->pin_reply(remote_bd_addr, TRUE, 4, &pincode))
+    {
+        printf("Pin Reply failed\n");
+    }*/
+}
+static void ssp_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name,
+                           uint32_t cod, bt_ssp_variant_t pairing_variant, uint32_t pass_key)
+{
+    printf("ssp_request_cb : name=%s variant=%d passkey=%u\n", bd_name->name, pairing_variant, pass_key);
+    if(BT_STATUS_SUCCESS != sBtInterface->ssp_reply(remote_bd_addr, pairing_variant, TRUE, pass_key))
+    {
+        printf("SSP Reply failed\n");
+    }
+}
+
+static void bond_state_changed_cb(bt_status_t status, bt_bdaddr_t *remote_bd_addr, bt_bond_state_t state)
+{
+    g_PairState = state;
+}
+
+static void acl_state_changed(bt_status_t status, bt_bdaddr_t *remote_bd_addr, bt_acl_state_t state)
+{
+    printf("acl_state_changed : remote_bd_addr=%02x:%02x:%02x:%02x:%02x:%02x, acl status=%s \n",
+    remote_bd_addr->address[0], remote_bd_addr->address[1], remote_bd_addr->address[2],
+    remote_bd_addr->address[3], remote_bd_addr->address[4], remote_bd_addr->address[5],
+    (state == BT_ACL_STATE_CONNECTED)?"ACL Connected" :"ACL Disconnected"
+    );
+}
+static void dut_mode_recv(uint16_t opcode, uint8_t *buf, uint8_t len)
+{
+    bdt_log("DUT MODE RECV : NOT IMPLEMENTED");
+}
+
+static void le_test_mode(bt_status_t status, uint16_t packet_count)
+{
+    bdt_log("LE TEST MODE END status:%s number_of_packets:%d", dump_bt_status(status), packet_count);
+}
+
+extern int timer_create (clockid_t, struct sigevent *__restrict, timer_t *__restrict);
+extern int timer_settime (timer_t, int, const struct itimerspec *__restrict, struct itimerspec *__restrict);
+
+static bool set_wake_alarm(uint64_t delay_millis, bool should_wake, alarm_cb cb, void *data)
+{
+
+   static timer_t timer;
+   static bool timer_created;
+
+   if (!timer_created) {
+      struct sigevent sigevent;
+      memset(&sigevent, 0, sizeof(sigevent));
+      sigevent.sigev_notify = SIGEV_THREAD;
+      sigevent.sigev_notify_function = (void (*)(union sigval))cb;
+      sigevent.sigev_value.sival_ptr = data;
+      timer_create(CLOCK_MONOTONIC, &sigevent, &timer);
+      timer_created = true;
+   }
+
+   struct itimerspec new_value;
+   new_value.it_value.tv_sec = delay_millis / 1000;
+   new_value.it_value.tv_nsec = (delay_millis % 1000) * 1000 * 1000;
+   new_value.it_interval.tv_sec = 0;
+   new_value.it_interval.tv_nsec = 0;
+   timer_settime(timer, 0, &new_value, NULL);
+   return true;
+}
+
+static int acquire_wake_lock(const char *lock_name)
+{
+    return BT_STATUS_SUCCESS;
+}
+
+static int release_wake_lock(const char *lock_name)
+{
+    return BT_STATUS_SUCCESS;
+}
+
+static bt_callbacks_t bt_callbacks = {
+    sizeof(bt_callbacks_t),
+    adapter_state_changed,
+    adapter_properties_changed, /*adapter_properties_cb */
+    NULL, /* remote_device_properties_cb */
+    NULL, /* device_found_cb */
+    discovery_state_changed, /* discovery_state_changed_cb */
+    pin_request_cb, /* pin_request_cb  */
+    ssp_request_cb, /* ssp_request_cb  */
+    bond_state_changed_cb, /*bond_state_changed_cb */
+    acl_state_changed, /* acl_state_changed_cb */
+    NULL, /* thread_evt_cb */
+    dut_mode_recv, /*dut_mode_recv_cb */
+    le_test_mode, /* le_test_mode_cb */
+    NULL,      /*energy_info_cb*/
+    NULL       /* hci_event_recv_cb */
+};
+
+static bt_os_callouts_t bt_os_callbacks = {
+     sizeof(bt_os_callouts_t),
+     set_wake_alarm,
+     acquire_wake_lock,
+     release_wake_lock
+};
+
+static void l2test_l2c_connect_ind_cb(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
+{
+
+    UINT16 result;
+
+    local_coc_cfg.credits = L2CAP_LE_DEFAULT_CREDIT;
+    local_coc_cfg.mtu = L2CAP_LE_DEFAULT_MTU;
+    local_coc_cfg.mps = L2CAP_LE_DEFAULT_MPS;
+    /* Verify if LE PSM  */
+   if (L2C_IS_VALID_LE_PSM(psm))
+   {
+       if (psm == 200)
+       {
+           printf("No Resources Available\n");
+           result = L2CAP_LE_NO_RESOURCES;
+           sL2capInterface->LeConnectRsp (bd_addr, id, lcid, result,L2CAP_LE_CONN_OK,&local_coc_cfg);
+       }
+       else if(psm == 201)
+       {
+           printf("L2CAP_LE_CONN_INSUFFI_AUTHORIZATION \n");
+           result = L2CAP_LE_INSUFFICIENT_AUTHORIZATION;
+           sL2capInterface->LeConnectRsp (bd_addr, id, lcid, result,L2CAP_LE_CONN_OK,&local_coc_cfg);
+       }
+       else
+       {
+
+           result = L2CAP_LE_CONN_OK;
+           sL2capInterface->LeConnectRsp (bd_addr, id, lcid, result,L2CAP_LE_CONN_OK,&local_coc_cfg);
+       }
+       return;
+   }
+   if((L2CAP_FCR_ERTM_MODE == g_Fcr_Mode) || (L2CAP_FCR_STREAM_MODE == g_Fcr_Mode)) {
+        sL2capInterface->ErtmConnectRsp(bd_addr, id, lcid, L2CAP_CONN_OK, L2CAP_CONN_OK, &t_ertm_info);
+    } else {
+        sL2capInterface->ConnectRsp(bd_addr, id, lcid, L2CAP_CONN_OK, L2CAP_CONN_OK);
+    }
+    {
+        tL2CAP_CFG_INFO cfg;
+        memcpy (&cfg ,&tl2cap_cfg_info,sizeof(tl2cap_cfg_info));
+        if ((!sL2capInterface->ConfigReq (lcid, &cfg)) && cfg.fcr_present
+              && cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
+            cfg.fcr.mode = L2CAP_FCR_BASIC_MODE;
+            cfg.fcr_present = FALSE;
+            sL2capInterface->ConfigReq (lcid, &cfg);
+        }
+    }
+    g_ConnectionState = CONNECT;
+    g_lcid = lcid;
+}
+
+static void l2test_l2c_connect_cfm_cb(UINT16 lcid, UINT16 result)
+{
+    t_le_chnl_info *le_conn_info = le_get_conn_info_by_lcid(lcid);
+    if (le_conn_info&&L2C_IS_VALID_LE_PSM(le_conn_info->psm))
+    {
+
+        if (result == L2CAP_LE_CONN_OK) {
+            g_ConnectionState = CONNECT;
+        }
+        else if(le_conn_info && !le_conn_info->is_server)
+        {
+            le_release_conn_info(le_conn_info);
+        }
+        return;
+    }
+#if 0
+    if (result == L2CAP_CONN_OK) {
+        L2cap_conn_state = L2CAP_CONN_SETUP;
+        tL2CAP_CFG_INFO cfg;
+        memcpy (&cfg ,&tl2cap_cfg_info,sizeof(tl2cap_cfg_info));
+        sL2capInterface->ConfigReq (lcid, &cfg);
+        g_imtu = cfg.mtu;
+        g_ConnectionState = CONNECT;
+        g_lcid = lcid;
+    }
+#endif
+}
+
+static void l2test_l2c_connect_pnd_cb(UINT16 lcid)
+{
+    g_ConnectionState = CONNECTING;
+}
+static void l2test_l2c_config_ind_cb(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
+{
+    p_cfg->result = L2CAP_CFG_OK;
+    p_cfg->fcr_present = FALSE;
+    if(p_cfg->mtu_present) g_omtu = p_cfg->mtu;
+    else g_omtu = L2CAP_DEFAULT_MTU;
+    sL2capInterface->ConfigRsp (lcid, p_cfg);
+    return;
+}
+
+static void l2test_l2c_config_cfm_cb(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
+{
+
+    /* For now, always accept configuration from the other side */
+    if (p_cfg->result == L2CAP_CFG_OK) {
+        printf("\nl2test_l2c_config_cfm_cb Success\n");
+    } else {
+
+     /* If peer has rejected FCR and suggested basic then try basic */
+    if (p_cfg->fcr_present) {
+        tL2CAP_CFG_INFO cfg;
+        memcpy (&cfg ,&tl2cap_cfg_info,sizeof(tl2cap_cfg_info));
+        cfg.fcr_present = FALSE;
+        sL2capInterface->ConfigReq (lcid, &cfg);
+        // Remain in configure state
+        return;
+    }
+    sL2capInterface->DisconnectReq(lcid);
+    }
+    if(0 == g_omtu) g_omtu = L2CAP_DEFAULT_MTU;
+}
+
+static void l2test_l2c_disconnect_ind_cb(UINT16 lcid, BOOLEAN ack_needed)
+{
+    t_le_chnl_info *le_conn_info = le_get_conn_info_by_lcid(lcid);
+    /* release the conn info entry if it'a  client */
+    if(le_conn_info &&  !le_conn_info->is_server)
+    {
+        le_release_conn_info(le_conn_info);
+    }
+    printf("l2test_le_l2c_disconnect_ind_cb, cid=0x%x, acks=%d\n", lcid, ack_needed);
+    if (ack_needed)
+    {
+        /* send L2CAP disconnect response */
+        sL2capInterface->DisconnectRsp(lcid);
+    }
+    g_ConnectionState = DISCONNECTING;
+    g_lcid = 0;
+}
+static void l2test_l2c_disconnect_cfm_cb(UINT16 lcid, UINT16 result)
+{
+    t_le_chnl_info *le_conn_info = le_get_conn_info_by_lcid(lcid);
+    /* release the conn info entry if it'a  client */
+    if(le_conn_info &&  !le_conn_info->is_server)
+    {
+        le_release_conn_info(le_conn_info);
+    }
+
+    printf("l2test_le_l2c_disconnect_cfm_cb, cid=0x%x, result=%d\n", lcid, result);
+    g_ConnectionState = DISCONNECT;
+    g_lcid = 0;
+}
+static void l2test_l2c_QoSViolationInd(BD_ADDR bd_addr)
+{
+    printf("l2test_l2c_QoSViolationInd\n");
+}
+static void l2test_l2c_data_ind_cb(UINT16 lcid, BT_HDR *p_buf)
+{
+    rcv_itration++;
+    printf("l2test_l2c_data_ind_cb:: itration=%d, event=%u, len=%u, "\
+            "offset=%u, layer_specific=%u\n",rcv_itration, p_buf->event,
+            p_buf->len, p_buf->offset, p_buf->layer_specific);
+    sL2capInterface->LeFreeBuf(p_buf);
+    printf("l2test_l2c_data_ind_cb:: event=%u, len=%u, offset=%u, layer_specific=%u\n",
+            p_buf->event, p_buf->len, p_buf->offset, p_buf->layer_specific);
+}
+static void l2test_l2c_congestion_ind_cb(UINT16 lcid, BOOLEAN is_congested)
+{
+    cong_status = is_congested;
+    printf("l2test_l2c_congestion_ind_cb is_congested %d\n ", is_congested);
+}
+
+static void l2test_l2c_tx_complete_cb (UINT16 lcid, UINT16 NoOfSDU)
+{
+    printf("l2test_l2c_tx_complete_cb, cid=0x%x, SDUs=%u\n", lcid, NoOfSDU);
+}
+
+/*
+static void l2c_echo_rsp_cb(UINT16 p)
+{
+    printf("Ping Response = %s\n", (L2CAP_PING_RESULT_OK==p) ?"Ping Reply OK" :(L2CAP_PING_RESULT_NO_LINK==p) ?"Link Could Not be setup" :"Remote L2cap did not reply");
+}
+*/
+/*LE-L2CAP Callback*/
+
+#if 0
+
+static void l2test_le_connect_ind_cb(BD_ADDR bd_addr, UINT16 lcid, UINT8 id,
+                                    tL2CAP_LE_CONN_INFO *conn_info)
+{
+    printf(" l2test_le_connect_ind_cb\n lcid=%u\n id=%u\n ls_psm %d\n "\
+            "le_mtu %d\n le_mps %d\n", lcid, id, conn_info->le_psm,
+            conn_info->le_mtu, conn_info->le_mps);
+    t_le_chnl_info *le_conn_info;
+    if (conn_info->le_psm == 200)
+    {
+        printf("No Resources Available\n");
+        conn_info->result = L2CAP_LE_NO_RESOURCES;
+        sL2capInterface->LeConnectRsp (bd_addr, id, lcid, conn_info);
+        return;
+    }
+    else if(conn_info->le_psm == 201)
+    {
+        printf("L2CAP_LE_CONN_INSUFFI_AUTHORIZATION \n");
+        conn_info->result = L2CAP_LE_INSUFFICIENT_AUTHORIZATION;
+        sL2capInterface->LeConnectRsp (bd_addr, id, lcid, conn_info);
+        return;
+    }
+
+    le_conn_info = le_get_conn_info(conn_info->le_psm, TRUE);
+
+    if(le_conn_info)
+    {
+        le_conn_info->loc_conn_info.result = L2CAP_LE_CONN_OK;
+        le_conn_info->lcid = lcid;
+        sL2capInterface->LeConnectRsp (bd_addr, id, lcid,
+                &le_conn_info->loc_conn_info);
+        memcpy(&le_conn_info->rmt_conn_info, conn_info,
+                sizeof(tL2CAP_LE_CONN_INFO));
+        g_ConnectionState = CONNECT;
+    }
+    else
+    {
+        printf("No PSM registered \n");
+        conn_info->result = L2CAP_LE_NO_PSM;
+        sL2capInterface->LeConnectRsp (bd_addr, id, lcid, conn_info);
+        return;
+    }
+}
+
+static void l2test_le_connect_cfm_cb(UINT16 lcid,
+        tL2CAP_LE_CONN_INFO *conn_info)
+{
+    t_le_chnl_info *le_conn_info;
+
+    printf(" l2test_le_connect_cfm_cb\n lcid=%u\n ls_psm %d\n le_mtu %d\n "\
+            "le_mps %d\n result %d\n",lcid, conn_info->le_psm,
+            conn_info->le_mtu, conn_info->le_mps, conn_info->result);
+
+    le_conn_info = le_get_conn_info(conn_info->le_psm, FALSE);
+
+    if (conn_info->result == L2CAP_LE_CONN_OK) {
+        g_ConnectionState = CONNECT;
+        if(le_conn_info)
+        {
+            memcpy(&le_conn_info->rmt_conn_info, conn_info,
+                    sizeof(tL2CAP_LE_CONN_INFO));
+            le_conn_info->lcid = lcid;
+        }
+    }
+    else if(le_conn_info && !le_conn_info->is_server)
+    {
+        le_release_conn_info(le_conn_info);
+    }
+}
+#endif
+
+/* L2CAP callback function structure */
+static tL2CAP_APPL_INFO l2test_l2c_appl = {
+  //  sizeof(l2test_l2c_appl),
+    l2test_l2c_connect_ind_cb,
+    l2test_l2c_connect_cfm_cb,
+    l2test_l2c_connect_pnd_cb,
+    l2test_l2c_config_ind_cb,
+    l2test_l2c_config_cfm_cb,
+    l2test_l2c_disconnect_ind_cb,
+    l2test_l2c_disconnect_cfm_cb,
+    l2test_l2c_QoSViolationInd,
+    l2test_l2c_data_ind_cb,
+    l2test_l2c_congestion_ind_cb,
+    l2test_l2c_tx_complete_cb
+};
+
+
+
+
+void bdt_init(void)
+{
+    bdt_log("INIT BT ");
+    status = sBtInterface->init(&bt_callbacks);
+    status = sBtInterface->set_os_callouts(&bt_os_callbacks);
+    check_return_status(status);
+}
+
+void bdt_enable(void)
+{
+    bdt_log("ENABLE BT");
+    if (bt_enabled) {
+        bdt_log("Bluetooth is already enabled");
+        return;
+    }
+    status = sBtInterface->enable(false);
+
+    check_return_status(status);
+}
+
+void bdt_disable(void)
+{
+    bdt_log("DISABLE BT");
+    if (!bt_enabled) {
+        bdt_log("Bluetooth is already disabled");
+        return;
+    }
+    status = sBtInterface->disable();
+
+    check_return_status(status);
+}
+
+void do_pairing(char *p)
+{
+    bt_bdaddr_t bd_addr = {{0}};
+    int transport = GATT_TRANSPORT_LE;
+    if(FALSE == GetBdAddr(p, &bd_addr))    return;    // arg1
+    if(BT_STATUS_SUCCESS != sBtInterface->create_bond(&bd_addr, transport))
+    {
+        printf("Failed to Initiate Pairing \n");
+        return;
+    }
+}
+
+void bdt_dut_mode_configure(char *p)
+{
+    int32_t mode = -1;
+
+    bdt_log("BT DUT MODE CONFIGURE");
+    if (!bt_enabled) {
+        bdt_log("Bluetooth must be enabled for test_mode to work.");
+        return;
+    }
+    mode = get_signed_int(&p, mode);
+    if ((mode != 0) && (mode != 1)) {
+        bdt_log("Please specify mode: 1 to enter, 0 to exit");
+        return;
+    }
+    status = sBtInterface->dut_mode_configure(mode);
+
+    check_return_status(status);
+}
+
+#define HCI_LE_RECEIVER_TEST_OPCODE 0x201D
+#define HCI_LE_TRANSMITTER_TEST_OPCODE 0x201E
+#define HCI_LE_END_TEST_OPCODE 0x201F
+
+void bdt_le_test_mode(char *p)
+{
+    int cmd;
+    unsigned char buf[3];
+    int arg1, arg2, arg3;
+
+    bdt_log("BT LE TEST MODE");
+    if (!bt_enabled) {
+        bdt_log("Bluetooth must be enabled for le_test to work.");
+        return;
+    }
+
+    memset(buf, 0, sizeof(buf));
+    cmd = get_int(&p, 0);
+    switch (cmd)
+    {
+        case 0x1: /* RX TEST */
+           arg1 = get_int(&p, -1);
+           if (arg1 < 0) bdt_log("%s Invalid arguments", __FUNCTION__);
+           buf[0] = arg1;
+           status = sBtInterface->le_test_mode(HCI_LE_RECEIVER_TEST_OPCODE, buf, 1);
+           break;
+        case 0x2: /* TX TEST */
+            arg1 = get_int(&p, -1);
+            arg2 = get_int(&p, -1);
+            arg3 = get_int(&p, -1);
+            if ((arg1 < 0) || (arg2 < 0) || (arg3 < 0))
+                bdt_log("%s Invalid arguments", __FUNCTION__);
+            buf[0] = arg1;
+            buf[1] = arg2;
+            buf[2] = arg3;
+            status = sBtInterface->le_test_mode(HCI_LE_TRANSMITTER_TEST_OPCODE, buf, 3);
+           break;
+        case 0x3: /* END TEST */
+            status = sBtInterface->le_test_mode(HCI_LE_END_TEST_OPCODE, buf, 0);
+           break;
+        default:
+            bdt_log("Unsupported command");
+            return;
+            break;
+    }
+    if (status != BT_STATUS_SUCCESS)
+    {
+        bdt_log("%s Test 0x%x Failed with status:0x%x", __FUNCTION__, cmd, status);
+    }
+    return;
+}
+
+void bdt_cleanup(void)
+{
+    bdt_log("CLEANUP");
+    sBtInterface->cleanup();
+}
+
+/*******************************************************************************
+ ** Console commands
+ *******************************************************************************/
+
+void do_help(char *p)
+{
+    int i = 0;
+    char line[128];
+//    int pos = 0;
+
+    while (console_cmd_list[i].name != NULL)
+    {
+        snprintf(line, 128,"%s", (char*)console_cmd_list[i].name);
+        bdt_log("%s %s\n", (char*)line, (char*)console_cmd_list[i].help);
+        i++;
+    }
+}
+
+void do_quit(char *p)
+{
+    bdt_shutdown();
+}
+
+/*******************************************************************
+ *
+ *  BT TEST  CONSOLE COMMANDS
+ *
+ *  Parses argument lists and passes to API test function
+ *
+*/
+
+void do_init(char *p)
+{
+    bdt_init();
+}
+
+void do_enable(char *p)
+{
+    bdt_enable();
+}
+
+void do_disable(char *p)
+{
+    bdt_disable();
+}
+void do_dut_mode_configure(char *p)
+{
+    bdt_dut_mode_configure(p);
+}
+
+void do_le_test_mode(char *p)
+{
+    bdt_le_test_mode(p);
+}
+
+void do_cleanup(char *p)
+{
+    bdt_cleanup();
+}
+
+
+void do_le_client_register(char *p)
+{
+    bt_status_t        Ret;
+    int Idx;
+    tBT_UUID    uuid;
+    bt_uuid_t    bt_uuid;
+
+    skip_blanks(&p);
+    Idx = atoi(p);
+
+    switch(Idx)
+    {
+    case 1:
+        uuid.len = LEN_UUID_128;
+        memcpy(&uuid.uu.uuid128, "\x00\x00\xA0\x0C\x00\x00\x00\x00\x01\x23\x45\x67\x89\xAB\xCD\xEF", 16); //0000A00C-0000-0000-0123-456789ABCDEF
+        memcpy(&bt_uuid.uu, "\x00\x00\xA0\x0C\x00\x00\x00\x00\x01\x23\x45\x67\x89\xAB\xCD\xEF", 16); //0000A00C-0000-0000-0123-456789ABCDEF
+        break;
+    case 2:
+        uuid.len = LEN_UUID_128;
+        memcpy(&uuid.uu.uuid128, "\x11\x22\xA0\x0C\x00\x00\x00\x00\x01\x23\x45\x67\x89\xAB\xCD\xEF", 16); //1122A00C-0000-0000-0123-456789ABCDEF
+        memcpy(&bt_uuid.uu, "\x11\x22\xA0\x0C\x00\x00\x00\x00\x01\x23\x45\x67\x89\xAB\xCD\xEF", 16); //1122A00C-0000-0000-0123-456789ABCDEF
+        break;
+    default:
+        printf("%s:: ERROR: no matching uuid \n", __FUNCTION__);
+        return;
+    }
+    if(Btif_gatt_layer)
+    {
+        Ret = sGattIfaceScan->client->register_client(&bt_uuid);
+        printf("%s:: ret value %d\n", __FUNCTION__,Ret);
+    }
+    else
+    {
+        g_client_if = sGattInterface->Register(&uuid, &sGattCB);
+        sleep(2);
+        sGattInterface->StartIf(g_client_if);
+    }
+}
+
+void do_le_client_deregister(char *p)
+{
+    bt_status_t        Ret;
+
+    if(Btif_gatt_layer)
+    {
+        if(0 == g_client_if_scan)
+        {
+            printf("%s:: ERROR: no application registered\n", __FUNCTION__);
+            return;
+        }
+        Ret = sGattIfaceScan->client->unregister_client(g_client_if_scan);
+        printf("%s:: Ret=%d\n", __FUNCTION__, Ret);
+    }
+    else
+    {
+        if(0 == g_client_if)
+        {
+            printf("%s:: ERROR: no application registered\n", __FUNCTION__);
+            return;
+        }
+        sGattInterface->Deregister(g_client_if);
+    }
+}
+
+void do_le_client_connect (char *p)
+{
+    BOOLEAN        Ret = false;
+    bt_bdaddr_t bd_addr = {{0}};
+    int transport = BT_TRANSPORT_BR_EDR;
+    transport = get_int(&p, -1);
+    if(FALSE == GetBdAddr(p, &bd_addr))    return;
+
+    if(transport == BT_TRANSPORT_BR_EDR)
+    {
+        //Outgoing Connection
+
+        //    g_SecLevel |= BTM_SEC_OUT_AUTHENTICATE;
+        //     g_SecLevel |= BTM_SEC_OUT_ENCRYPT ;
+        g_PSM= 1;
+        g_SecLevel = 0;
+        printf("g_SecLevel = %d \n", g_SecLevel);
+        sL2capInterface->RegisterPsm(g_PSM, g_ConnType, g_SecLevel /*BTM_SEC_IN_AUTHORIZE */);
+        sleep(3);
+
+        l2c_connect(&bd_addr);
+    }
+    else if(Btif_gatt_layer)
+    {
+        Ret = sGattIfaceScan->client->connect(g_client_if_scan, &bd_addr, TRUE, transport);
+    }
+    else
+    {
+        Ret = sGattInterface->Connect(g_client_if, bd_addr.address, TRUE, transport);
+    }
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+
+void do_le_client_refresh (char *p)
+{
+    BOOLEAN        Ret;
+    bt_bdaddr_t bd_addr = {{0}};
+    if(FALSE == GetBdAddr(p, &bd_addr))    return;
+
+    if(Btif_gatt_layer)
+    {
+        Ret = sGattIfaceScan->client->refresh(g_client_if_scan, &bd_addr);
+        printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+    }
+}
+
+void do_le_conn_param_update(char *p)
+{
+    BOOLEAN        Ret;
+    bt_bdaddr_t bd_addr = {{0}};
+    int min_interval = 24;
+    int max_interval = 40;
+    int latency = 0;
+    int timeout = 2000;
+    min_interval =  get_int(&p, -1);
+    max_interval =  get_int(&p, -1);
+    latency      =  get_int(&p, -1);
+    if(!min_interval)
+        min_interval = 24;
+    if(!max_interval)
+        max_interval = 40;
+    if(FALSE == GetBdAddr(p, &bd_addr))    return;
+    Ret = sGattIfaceScan->client->conn_parameter_update(&bd_addr,min_interval,max_interval,latency,timeout);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+
+}
+
+void do_le_client_connect_auto (char *p)
+{
+    BOOLEAN        Ret;
+    bt_bdaddr_t bd_addr = {{0}};
+    if(FALSE == GetBdAddr(p, &bd_addr))    return;
+
+    if(Btif_gatt_layer)
+    {
+        Ret = sGattIfaceScan->client->connect(g_client_if_scan, &bd_addr, FALSE,BT_TRANSPORT_LE);
+    }
+    else
+    {
+        Ret = sGattInterface->Connect(g_client_if, bd_addr.address, FALSE,BT_TRANSPORT_LE);
+    }
+    printf("%s:: Ret=%d \n", __FUNCTION__,Ret );
+}
+
+
+void do_le_client_disconnect (char *p)
+{
+    bt_status_t        Ret;
+    bt_bdaddr_t bd_addr = {{0}};
+    int transport = BT_TRANSPORT_BR_EDR;
+    transport = get_int(&p, -1);
+    if(FALSE == GetBdAddr(p, &bd_addr))    return;
+
+    if(transport == BT_TRANSPORT_BR_EDR)
+    {
+        Ret = sL2capInterface->DisconnectReq(g_lcid);
+    }
+    else if(Btif_gatt_layer)
+    {
+        Ret = sGattIfaceScan->client->disconnect(g_client_if_scan, &bd_addr, g_conn_id);
+    }
+    else
+    {
+        Ret = sGattInterface->Disconnect(g_conn_id);
+    }
+    printf("%s:: Ret=%d \n", __FUNCTION__,Ret );
+}
+
+void do_le_client_scan_start (char *p)
+{
+    bt_status_t        Ret;
+    Ret = sGattIfaceScan->client->scan(TRUE);
+    printf("%s:: Ret=%d \n", __FUNCTION__,Ret );
+}
+
+void do_le_client_scan_stop (char *p)
+{
+    bt_status_t        Ret;
+    Ret = sGattIfaceScan->client->scan(FALSE);
+    printf("%s:: Ret=%d \n", __FUNCTION__,Ret );
+}
+
+void do_le_client_listen_start (char *p)
+{
+    bt_status_t        Ret;
+    Ret = sGattIfaceScan->client->listen(g_client_if_scan,TRUE);
+    printf("%s:: Ret=%d \n", __FUNCTION__,Ret );
+}
+
+void do_le_client_listen_stop (char *p)
+{
+    bt_status_t        Ret;
+    Ret = sGattIfaceScan->client->listen(g_client_if_scan,FALSE);
+    printf("%s:: Ret=%d \n", __FUNCTION__,Ret );
+}
+
+void do_le_client_set_adv_data(char *p)
+{
+    bt_status_t        Ret;
+    bool              SetScanRsp        = FALSE;
+    bool              IncludeName        = TRUE;
+    bool              IncludeTxPower    = FALSE;
+    int               min_conn_interval = 100;
+    int               max_conn_interval = 1000;
+
+    SetScanRsp         = get_int(&p, -1);  // arg1  Other than zero will be considered as true.
+    IncludeName     = get_int(&p, -1);  // arg2  Other than zero will be considered as true.
+    IncludeTxPower     = get_int(&p, -1);  // arg3  Other than zero will be considered as true.
+    min_conn_interval     = get_int(&p, -1);  // arg3  Other than zero will be considered as true.
+    max_conn_interval     = get_int(&p, -1);  // arg3  Other than zero will be considered as true.
+
+    //To start with we are going with hard-code values.
+    Ret = sGattIfaceScan->client->set_adv_data(/*g_server_if*/ g_server_if_scan /*g_client_if_scan*/, SetScanRsp, IncludeName, IncludeTxPower, min_conn_interval, max_conn_interval, 0,8, "QUALCOMM", 0, NULL,0,NULL);
+    printf("%s:: Ret=%d \n", __FUNCTION__,Ret );
+}
+void do_le_client_set_adv_mode(char *p)
+{
+    tBTA_DM_DISC disc_mode;
+    tBTA_DM_CONN conn_mode;
+
+    disc_mode = get_int(&p,-1);
+    conn_mode = get_int(&p,-1);
+    printf("%s:: discoverable  mode=%d  connectable _mode=%d \n", __FUNCTION__,disc_mode,conn_mode );
+    sGattInterface->cSetVisibility(disc_mode,conn_mode);
+
+}
+
+void do_le_client_multi_adv_set_inst_data(char *p)
+{
+    bt_status_t        Ret;
+    bool              SetScanRsp        = FALSE;
+    bool              IncludeName        = TRUE;
+    bool              IncludeTxPower    = TRUE;
+
+    SetScanRsp         = get_int(&p, -1);  // arg1  Other than zero will be considered as true.
+    IncludeName     = get_int(&p, -1);  // arg2  Other than zero will be considered as true.
+    IncludeTxPower     = get_int(&p, -1);  // arg3  Other than zero will be considered as true.
+
+    //To start with we are going with hard-code values.
+    Ret = sGattIfaceScan->client->multi_adv_set_inst_data(g_client_if_scan /*g_client_if_scan*/, SetScanRsp, IncludeName, IncludeTxPower,0,8, "QUALCOMM", 0, NULL,0,NULL);
+    printf("%s:: Ret=%d \n", __FUNCTION__,Ret );
+}
+
+void do_le_client_adv_update(char *p)
+{
+    bt_status_t        Ret;
+    int               TxPower    = 3;
+    int               chnlMap    = 7;
+    int               min_interval = 160;
+    int               max_interval = 240;
+    int               adv_type    = 3 ;//non-connectable undirect
+    int               adv_if   =  g_server_if_scan;
+    int               timeout_s =   30;
+
+    adv_if       =  get_int(&p, -1);
+    min_interval =  get_int(&p, -1);
+    max_interval =  get_int(&p, -1);
+    adv_type     =  get_int(&p, -1);
+    chnlMap      =  get_int(&p, -1);
+    TxPower      =  get_int(&p, -1);
+    timeout_s    =  get_int(&p, -1);
+    //To start with we are going with hard-code values.
+    Ret = sGattIfaceScan->client->multi_adv_update(adv_if, min_interval, max_interval,adv_type,chnlMap,TxPower, timeout_s);
+    printf("%s:: Ret=%d \n", __FUNCTION__,Ret );
+}
+
+void do_le_client_adv_enable(char *p)
+{
+    bt_status_t       Ret;
+    int               TxPower    = 4;
+    int               chnlMap    = 7;
+    int               min_interval = 30;
+    int               max_interval = 60;
+    int               adv_type    = 0; //connectable undirect
+    int               adv_if   =  g_server_if_scan;
+    int               timeout_s = 30;
+
+    adv_if       =  get_int(&p, -1);
+    min_interval =  get_int(&p, -1);
+    max_interval =  get_int(&p, -1);
+    adv_type     =  get_int(&p, -1);
+    chnlMap      =  get_int(&p, -1);
+    TxPower      =  get_int(&p, -1);
+    timeout_s    =  get_int(&p, -1);
+    Ret = sGattIfaceScan->client->multi_adv_enable(adv_if,min_interval,max_interval,adv_type,chnlMap,TxPower, timeout_s);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+
+void do_le_client_adv_disable(char *p)
+{
+    bt_status_t   Ret;
+    int           adv_if = g_server_if_scan;
+
+    adv_if = get_int(&p, -1);
+    Ret = sGattIfaceScan->client->multi_adv_disable(adv_if);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+
+void do_le_client_configureMTU(char *p)
+{
+    tGATT_STATUS Ret =0;
+    UINT16 mtu = 23;
+
+    printf("%s:: mtu :%d\n", __FUNCTION__, mtu);
+    Ret = sGattInterface->cConfigureMTU(g_conn_id, mtu);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+
+void do_le_client_discover(char *p)
+{
+    int        uuid_len = 0;
+    tGATT_STATUS Ret =0;
+    tGATT_DISC_PARAM param;
+    tGATT_DISC_TYPE disc_type; //GATT_DISC_SRVC_ALL , GATT_DISC_SRVC_BY_UUID
+
+    disc_type = get_int(&p, -1);  // arg1
+    param.s_handle = get_hex(&p, -1);  // arg2
+    param.e_handle = get_hex(&p, -1);  // arg3
+
+    uuid_len    = get_int(&p, -1);  // arg4 - Size in bits for the uuid (16, 32, or 128)
+    if((16==uuid_len) || (32==uuid_len) || (128==uuid_len))
+    {
+        param.service.len = uuid_len/8;
+    }
+    else
+    {
+        printf("%s::ERROR - Invalid Parameter. UUID Len should be either 16/32/128 \n",__FUNCTION__);
+        return;
+        }
+
+    switch(param.service.len)
+    {
+        case 2: //16 bit uuid
+            param.service.uu.uuid16 = get_hex(&p, -1); // arg5
+            break;
+
+        case 4: //32 bit uuid
+            param.service.uu.uuid32 = get_hex(&p, -1); // arg5
+            break;
+
+        case 16: //128 bit uuid
+            *((unsigned int*)&param.service.uu.uuid128[12]) = get_hex(&p, -1);
+            *((unsigned int*)&param.service.uu.uuid128[8]) = get_hex(&p, -1);
+            *((unsigned int*)&param.service.uu.uuid128[4]) = get_hex(&p, -1);
+            *((unsigned int*)param.service.uu.uuid128) = get_hex(&p, -1);    //arg5
+
+            break;
+        default:
+            printf("%s::ERROR - Invalid Parameter. UUID Len should  \n",__FUNCTION__);
+            return;
+    }
+
+    printf("%s:: disc_type = %d, uuid=%04x \n", __FUNCTION__, disc_type, param.service.uu.uuid16);
+
+    //if(FALSE == GetDiscType(p, &disc_type))    return;        //TODO - add the function if user input is needed
+    Ret = sGattInterface->cDiscover(g_conn_id, disc_type, &param);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+
+
+void do_le_client_read(char *p)
+{
+    int i =0;
+    int        uuid_len = 0;
+    tGATT_STATUS Ret = 0;
+    tGATT_READ_TYPE read_type;
+    int auth_req;
+    tGATT_READ_PARAM readBuf;// = {GATT_AUTH_REQ_NONE, 0x201};
+
+    //Parse and copy command line arguments
+    read_type = get_int(&p, -1); // arg2
+    auth_req = get_int(&p, -1); // arg2
+
+    switch(read_type)
+    {
+    case GATT_READ_BY_TYPE:
+    case GATT_READ_CHAR_VALUE:
+
+        readBuf.service.auth_req     = auth_req;
+        readBuf.service.s_handle     = get_hex(&p, -1);  // arg2
+        readBuf.service.e_handle     = get_hex(&p, -1);  // arg3
+
+        uuid_len    = get_int(&p, -1);  // arg4 - Size in bits for the uuid (16, 32, or 128)
+        if((16==uuid_len) || (32==uuid_len) || (128==uuid_len))
+        {
+            readBuf.service.uuid.len = uuid_len/8;
+        }
+        else
+        {
+            printf("%s::ERROR - Invalid Parameter. UUID Len should be either 16/32/128 \n",__FUNCTION__);
+            return;
+        }
+
+        switch(readBuf.service.uuid.len)
+        {
+            case 2: //16 bit uuid
+                readBuf.service.uuid.uu.uuid16 = get_hex(&p, -1); // arg5
+                break;
+
+            case 4: //32 bit uuid
+                readBuf.service.uuid.uu.uuid32 = get_hex(&p, -1); // arg5
+                break;
+
+            case 16: //128 bit uuid
+                *((unsigned int*)&readBuf.service.uuid.uu.uuid128[12]) = get_hex(&p, -1);
+                *((unsigned int*)&readBuf.service.uuid.uu.uuid128[8]) = get_hex(&p, -1);
+                *((unsigned int*)&readBuf.service.uuid.uu.uuid128[4]) = get_hex(&p, -1);
+                *((unsigned int*)readBuf.service.uuid.uu.uuid128) = get_hex(&p, -1);    //arg5
+
+                break;
+            default:
+                printf("%s::ERROR - Invalid Parameter. UUID Len should be either 4/8/32characters, which corresponds <16/32/128> bits \n",__FUNCTION__);
+                return;
+        }
+        break;
+
+
+    case GATT_READ_BY_HANDLE:
+        readBuf.by_handle.handle = get_hex(&p, -1);
+        readBuf.by_handle.auth_req = auth_req;
+        break;
+
+    case GATT_READ_MULTIPLE:
+        readBuf.read_multiple.auth_req = auth_req;
+        readBuf.read_multiple.num_handles = get_hex(&p, -1); //arg 2
+        if(readBuf.read_multiple.num_handles > 10)
+        {
+            printf(":: ERROR - invalid param. Max handle value is 10. \n");
+            return;
+        }
+        for(i=0; i<readBuf.read_multiple.num_handles; i++)
+        {
+            readBuf.read_multiple.handles[i] = get_hex(&p, -1); //arg 3 ... N
+        }
+        printf("%s:: Read by MultipleHandle \t Number of handles=%04x \n", __FUNCTION__, readBuf.read_multiple.num_handles);
+        break;
+
+    case GATT_READ_PARTIAL:
+        readBuf.partial.auth_req = auth_req;
+        readBuf.partial.handle = get_hex(&p, -1); //arg 2
+        readBuf.partial.offset = get_hex(&p, -1); //arg 3
+        printf("%s:: Read by Descriptor \t handle=%04x \t offset=%04x \n", __FUNCTION__, readBuf.partial.handle, readBuf.partial.offset);
+        break;
+
+    }
+
+    Ret = sGattInterface->cRead(g_conn_id, read_type, &readBuf);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+
+void copy_string(char *dest, char *source)
+{
+   int i = 2;
+   while(i)
+   {
+      *dest = *source;
+      source++;
+      dest++;
+      i--;
+   }
+   *dest = '\0';
+}
+
+void do_le_client_write(char *p)
+{
+    int i;
+    tGATT_STATUS Ret = 0;
+    tGATT_WRITE_TYPE write_type;
+    int auth_req = 0;
+    tGATT_VALUE writeBuf;// = {GATT_AUTH_REQ_NONE, 0x201};
+
+    write_type = get_int(&p, -1); // arg1
+    auth_req = get_int(&p, -1); // arg2
+
+    writeBuf.conn_id = g_conn_id;
+    writeBuf.auth_req = auth_req;
+    writeBuf.handle     = get_hex(&p, -1);  // arg3
+    writeBuf.offset     = get_hex(&p, -1);  //arg4
+    writeBuf.len         = get_int(&p, -1); //arg5
+
+
+    if(writeBuf.len > GATT_MAX_ATTR_LEN )
+    {
+        printf("%s:: ERROR - invalid param. Max length for Write is 600 \n",__FUNCTION__);
+        return;
+    }
+    memset(&(writeBuf.value[0]), 0, GATT_MAX_ATTR_LEN);
+    for (i = 0; i < writeBuf.len; i++)
+    {
+        writeBuf.value[i] = get_hex_byte(&p, 0);
+    }
+
+    Ret = sGattInterface->cWrite(g_conn_id, write_type, &writeBuf);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+void do_le_execute_write(char *p)
+{
+    BOOLEAN is_execute;
+    tGATT_STATUS Ret = 0;
+
+    is_execute = get_int(&p, -1); // arg1
+
+    printf("%s:: is_execute=%d \n", __FUNCTION__, is_execute);
+    Ret = sGattInterface->cExecuteWrite(g_conn_id, is_execute);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+void do_le_set_idle_timeout(char *p)
+{
+    int idle_timeout;
+    bt_bdaddr_t bd_addr = {{0}};
+        if(FALSE == GetBdAddr(p, &bd_addr))    return;
+    idle_timeout = get_int(&p, -1); //arg2
+    sGattInterface->cSetIdleTimeout(bd_addr.address, idle_timeout);
+
+}
+
+
+/*******************************************************************************
+ ** GATT SERVER API commands
+ *******************************************************************************/
+void do_le_server_register(char *p)
+{
+    bt_status_t        Ret;
+    int Idx;
+    tBT_UUID    uuid;
+    bt_uuid_t    bt_uuid;
+    skip_blanks(&p);
+    Idx = atoi(p);
+    switch(Idx)
+    {
+    case 1:
+        uuid.len = LEN_UUID_128;
+        memcpy(&uuid.uu.uuid128, "\x00\x00\xA0\x0C\x00\x00\x00\x00\x01\x23\x45\x67\x89\xAB\xCD\xEF", 16); //0000A00C-0000-0000-0123-456789ABCDEF
+        memcpy(&bt_uuid.uu, "\x00\x00\xA0\x0C\x00\x00\x00\x00\x01\x23\x45\x67\x89\xAB\xCD\xEF", 16); //0000A00C-0000-0000-0123-456789ABCDEF
+        break;
+    case 2:
+        uuid.len = LEN_UUID_128;
+        memcpy(&uuid.uu.uuid128, "\x11\x22\xA0\x0C\x00\x00\x00\x00\x01\x23\x45\x67\x89\xAB\xCD\xEF", 16); //1122A00C-0000-0000-0123-456789ABCDEF
+        memcpy(&bt_uuid.uu, "\x11\x22\xA0\x0C\x00\x00\x00\x00\x01\x23\x45\x67\x89\xAB\xCD\xEF", 16); //1122A00C-0000-0000-0123-456789ABCDEF
+        break;
+    default:
+        printf("%s:: ERROR: no matching uuid \n", __FUNCTION__);
+        return;
+    }
+
+    if(Btif_gatt_layer)
+    {
+        Ret = sGattIfaceScan->server->register_server(&bt_uuid);
+        printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+    }
+    else
+    {
+        g_server_if = sGattInterface->Register(&uuid, &sGattCB);
+        printf("%s:: g_server_if=%d \n", __FUNCTION__, g_server_if);
+    }
+
+}
+
+void do_le_server_deregister(char *p)
+{
+    bt_status_t        Ret;
+    if(0 == g_server_if)
+    {
+        printf("%s:: ERROR: no application registered\n", __FUNCTION__);
+        return;
+    }
+    sGattInterface->Deregister(g_server_if);
+    Ret = sGattIfaceScan->server->unregister_server(g_server_if_scan);
+    printf("%s::Ret = %d\n", __FUNCTION__,Ret);
+}
+
+void do_le_server_add_service(char *p)
+{
+    bt_status_t     Ret = 0;
+
+    //Later take this value as cmd line
+    btgatt_srvc_id_t    srvc_id;
+    memcpy(&srvc_id.id.uuid.uu, "\x00\x00\x18\x00\x00\x00\x10\x00\x80\x00\x00\x80\x5f\x9b\x34\xfb", 16);  //00001800-0000-1000-8000-00805f9b34fb
+
+
+    srvc_id.id.inst_id    = 1;//
+    srvc_id.is_primary    = BTGATT_SERVICE_TYPE_PRIMARY; // BTGATT_SERVICE_TYPE_SECONDARY
+    Ret = sGattIfaceScan->server->add_service(g_server_if_scan, &srvc_id, 1/*num_handles*/);
+    printf("%s:: Ret=%d \n", __FUNCTION__,Ret );
+}
+
+void do_le_server_connect (char *p)
+{
+    BOOLEAN        Ret;
+    bt_bdaddr_t bd_addr = {{0}};
+    if(FALSE == GetBdAddr(p, &bd_addr))    return;
+    Ret = sGattIfaceScan->server->connect(g_server_if_scan, &bd_addr, TRUE, BT_TRANSPORT_LE);
+    printf("%s:: Ret=%d \n", __FUNCTION__,Ret );
+}
+
+void do_le_server_connect_auto (char *p)
+{
+    BOOLEAN        Ret;
+    bt_bdaddr_t bd_addr = {{0}};
+    if(FALSE == GetBdAddr(p, &bd_addr))    return;
+    Ret = sGattIfaceScan->server->connect(g_server_if_scan, &bd_addr, FALSE, BT_TRANSPORT_LE);
+    printf("%s:: Ret=%d \n", __FUNCTION__,Ret );
+}
+
+
+void do_le_server_disconnect (char *p)
+{
+    bt_status_t        Ret;
+    bt_bdaddr_t bd_addr = {{0}};
+    if(FALSE == GetBdAddr(p, &bd_addr))    return;
+    Ret = sGattIfaceScan->server->disconnect(g_server_if_scan, &bd_addr, g_conn_id);
+    printf("%s:: Ret=%d \n", __FUNCTION__,Ret );
+}
+
+/**************************************************
+**L2CAP for BR/EDR conn
+***************************************************/
+
+
+
+void do_l2cap_init(char *p)
+{
+
+    memset(&tl2cap_cfg_info, 0, sizeof(tl2cap_cfg_info));
+    memset(&le_conn_info, 0, sizeof(le_conn_info));
+    //Use macros for the constants
+    tl2cap_cfg_info.mtu_present = TRUE;
+    tl2cap_cfg_info.mtu = g_imtu;
+    tl2cap_cfg_info.flush_to_present = TRUE;
+    tl2cap_cfg_info.flush_to = 0xffff;
+    //use other param if needed
+    tl2cap_cfg_info.fcr_present = g_Fcr_Present;
+    tl2cap_cfg_info.fcr.mode = g_Fcr_Mode;
+    tl2cap_cfg_info.fcs = 0;
+    tl2cap_cfg_info.fcs_present = 1;
+    le_conn_info.init_credits = L2CAP_LE_MAX_CREDIT;
+    le_conn_info.le_mtu = L2CAP_LE_DEFAULT_MTU;
+    le_conn_info.le_mps = L2CAP_LE_DEFAULT_MPS;
+    le_conn_info.le_psm = 0x80; //dynamic le psm starts from 0x80
+    if(L2CAP_FCR_ERTM_MODE == tl2cap_cfg_info.fcr.mode)
+    {
+        tl2cap_cfg_info.fcr = ertm_fcr_opts_def;
+    }
+    else if(L2CAP_FCR_STREAM_MODE == tl2cap_cfg_info.fcr.mode)
+    {
+        tl2cap_cfg_info.fcr = stream_fcr_opts_def;
+    }
+    //Load L2cap Interface
+    else if(NULL == sL2capInterface)
+    {
+        printf("Get L2cap testapp interfaces\n");
+        sL2capInterface = sBtInterface->get_testapp_interface(TEST_APP_L2CAP);
+    }
+    tl2cap_cfg_info.fcr.tx_win_sz = 3;
+    //Initialize ERTM Parameters
+    t_ertm_info.preferred_mode = g_Fcr_Mode;
+    t_ertm_info.allowed_modes = g_Ertm_AllowedMode;
+    t_ertm_info.user_rx_buf_size = BT_DEFAULT_BUFFER_SIZE;
+    t_ertm_info.user_tx_buf_size = BT_DEFAULT_BUFFER_SIZE;
+    t_ertm_info.fcr_rx_buf_size = BT_DEFAULT_BUFFER_SIZE;
+    t_ertm_info.fcr_tx_buf_size = BT_DEFAULT_BUFFER_SIZE;
+    //Load L2cap Interface
+    sL2capInterface->Init(&l2test_l2c_appl);
+}
+
+
+/*
+static int l2c_pair(char *p)
+{
+    bt_bdaddr_t bd_addr = {{0}};
+    int transport = BT_TRANSPORT_BR_EDR;
+    transport = get_int(&p, -1);
+    GetBdAddr(p, &bd_addr);
+    if(BT_STATUS_SUCCESS != sBtInterface->create_bond(&bd_addr,transport))
+    {
+        printf("Failed to Initiate Pairing \n");
+        return FALSE;
+    }
+     sleep(20);
+     return TRUE;
+}
+*/
+
+static UINT16 do_l2cap_connect(bt_bdaddr_t * bd_addr)
+{
+
+    if((L2CAP_FCR_STREAM_MODE == g_Fcr_Mode) || (L2CAP_FCR_ERTM_MODE == g_Fcr_Mode)) {
+        return sL2capInterface->ErtmConnectReq(g_PSM, bd_addr->address, &t_ertm_info);
+    } else {
+        return sL2capInterface->Connect(g_PSM, bd_addr);
+    }
+}
+
+static void l2c_connect(bt_bdaddr_t *bd_addr)
+{
+    do_l2cap_connect(bd_addr);
+}
+
+
+BOOLEAN do_l2cap_disconnect(char *p)
+{
+    return sL2capInterface->DisconnectReq(g_lcid);
+}
+
+/* LE-L2CAP functionalities */
+static t_le_chnl_info *le_allocate_conn_info(UINT16 psm, BOOLEAN is_server)
+{
+    t_le_chnl_info    *p_le_chnl_info = &le_chnl_conn_info[0];
+    UINT16      i;
+
+    for (i = 0; i < MAX_L2CAP_CLIENTS; i++, p_le_chnl_info++)
+    {
+        if (!p_le_chnl_info->in_use)
+        {
+            p_le_chnl_info->in_use = TRUE;
+            p_le_chnl_info->is_server = is_server;
+            p_le_chnl_info->psm    = psm;
+            return p_le_chnl_info;
+        }
+    }
+    return (NULL);
+
+}
+
+static t_le_chnl_info *le_get_conn_info(UINT16 psm, BOOLEAN is_server)
+{
+    t_le_chnl_info    *p_le_chnl_info = &le_chnl_conn_info[0];
+    UINT16      i;
+
+    for (i = 0; i < MAX_L2CAP_CLIENTS; i++, p_le_chnl_info++)
+    {
+        if ((p_le_chnl_info->in_use) && (p_le_chnl_info->psm == psm)
+                && (is_server == p_le_chnl_info->is_server))
+        {
+            return p_le_chnl_info;
+        }
+    }
+    return NULL;
+
+}
+
+static t_le_chnl_info *le_get_conn_info_by_lcid(UINT16 lcid)
+{
+    t_le_chnl_info    *p_le_chnl_info = &le_chnl_conn_info[0];
+    UINT16      i;
+
+    for (i = 0; i < MAX_L2CAP_CLIENTS; i++, p_le_chnl_info++)
+    {
+        if ((p_le_chnl_info->in_use) && (p_le_chnl_info->lcid == lcid))
+        {
+            return p_le_chnl_info;
+        }
+    }
+    return NULL;
+
+}
+
+static BOOLEAN le_release_conn_info(t_le_chnl_info *le_conn_info)
+{
+    if (le_conn_info && (le_conn_info->in_use))
+    {
+        le_conn_info->in_use = FALSE;
+        le_conn_info->is_server = 0;
+        le_conn_info->psm    = 0;
+        memset(le_conn_info, 0, sizeof(tL2CAP_LE_CONN_INFO));
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static void do_start_advertisment(char *p)
+{
+    tBT_UUID    uuid;
+    int option = get_int(&p, -1);
+    int start = get_int(&p, -1);
+
+    uuid.len = LEN_UUID_128;
+    memcpy(&uuid.uu.uuid128, "\x11\x22\xA0\x0D\x00\x00\x00\x00\x01\x23\x45\x67\x89\xAB\xCD\xEF", 16); //1122A00D-0000-0000-0123-456789ABCDEF
+
+    if ((g_le_coc_if == 0) && option)
+        g_le_coc_if = sGattInterface->Register(&uuid, &sGattCB);
+    printf("Gatt Registration Done\n");
+
+    if( option)
+    {
+        if (start == 1)
+            status = sGattInterface->Listen(g_le_coc_if, start, NULL);
+        else if (start == 0)
+            status = sGattInterface->Listen(g_le_coc_if, start, NULL);
+        else
+        {
+            printf("Unknown parameter\n");
+            return;
+        }
+    }
+    else
+    {
+        if (start == 1)
+            status = sGattInterface->Listen(g_server_if_scan, start, NULL);
+        else if (start == 0)
+            status = sGattInterface->Listen(g_server_if_scan, start, NULL);
+        else
+        {
+            printf("Unknown parameter\n");
+            return;
+        }
+    }
+    printf("Gatt Listen status is %d\n", status);
+}
+
+UINT16 do_le_l2cap_coc_flow_ctrl(char *p)
+{
+    UINT16 lcid = get_int(&p, -1);
+
+    UINT16 credits = get_int(&p, -1);
+
+    printf("\ndo_le_l2cap_coc_flow_ctrl lcid = %d, credits = %d\n", lcid, credits);
+    return sL2capInterface->LeFlowControl(lcid, credits);
+}
+static void le_l2cap_coc_flow_ctrl(char *p)
+{
+    printf("In le_l2cap_coc_flow_ctrl\n");
+    do_le_l2cap_coc_flow_ctrl(p);
+}
+
+UINT16 do_le_l2cap_coc_connect(char *p)
+{
+    int le_initiator_sec_level;
+    UINT16 le_coc_seclevel = 0;
+    bt_bdaddr_t bd_addr = {{0}};
+    UINT16 le_psm = get_int(&p, -1);
+
+
+    t_le_chnl_info *le_conn_info = le_allocate_conn_info(le_psm, FALSE);
+
+    if(le_conn_info)
+    {
+        le_conn_info->loc_conn_info.le_psm = le_psm;
+        le_conn_info->loc_conn_info.le_mtu = get_int(&p, -1);
+        le_conn_info->loc_conn_info.le_mps = get_int(&p, -1);
+        le_conn_info->loc_conn_info.init_credits = get_int(&p, -1);
+        le_initiator_sec_level = get_int(&p, -1);
+        if(FALSE == GetBdAddr(p, &bd_addr))    return FALSE;
+    }
+    else
+        return FALSE;
+
+    if (le_initiator_sec_level == 0)
+    {
+        le_coc_seclevel |= BTM_SEC_NONE;
+    }
+    else if (le_initiator_sec_level == 1)
+    {
+        le_coc_seclevel |= BTM_SEC_OUT_AUTHENTICATE;
+    }
+    else if (le_initiator_sec_level == 2)
+    {
+        le_coc_seclevel |= BTM_SEC_OUT_ENCRYPT;
+        le_coc_seclevel |= BTM_SEC_OUT_AUTHENTICATE;
+    }
+    else
+    {
+        printf("Security level not supported");
+        return FALSE;
+    }
+
+    printf("g_SecLevel = %d \n", le_coc_seclevel);
+    sL2capInterface->RegisterLePsm(le_conn_info->loc_conn_info.le_psm, TRUE,
+            le_coc_seclevel, g_BleEncKeySize);
+    sleep(3);
+    local_coc_cfg.credits = le_conn_info->loc_conn_info.init_credits;
+    local_coc_cfg.mtu = le_conn_info->loc_conn_info.le_mtu;
+    local_coc_cfg.mps = le_conn_info->loc_conn_info.le_mps;
+    printf("\ndo_l2cap_connect:::::::: psm %d mtu %d mps %d init_credit %d \n",
+            le_conn_info->loc_conn_info.le_psm, le_conn_info->loc_conn_info.le_mtu,
+            le_conn_info->loc_conn_info.le_mps, le_conn_info->loc_conn_info.init_credits);
+
+    return sL2capInterface->LeConnect(le_conn_info->loc_conn_info.le_psm, ( UINT8 * )&bd_addr.address, &local_coc_cfg);
+}
+
+static void le_l2cap_coc_connect(char *svr)
+{
+    do_le_l2cap_coc_connect(svr);
+}
+
+static void le_l2cap_listen(char *p)
+{
+    int le_rspndr_sec_level;
+    UINT16 le_coc_seclevel = 0;
+    UINT16 le_psm = get_int(&p, -1);
+    t_le_chnl_info *le_conn_info = le_get_conn_info(le_psm, TRUE);
+
+    if(!le_conn_info)
+    {
+        le_conn_info = le_allocate_conn_info(le_psm, TRUE);
+    }
+    else
+    {
+        printf("ALready listening on same channel");
+        return;
+    }
+
+    if(le_conn_info)
+    {
+        le_conn_info->loc_conn_info.le_psm = le_psm;
+        le_conn_info->loc_conn_info.le_mtu = get_int(&p, -1);
+        le_conn_info->loc_conn_info.le_mps = get_int(&p, -1);
+        le_conn_info->loc_conn_info.init_credits = get_int(&p, -1);
+        le_rspndr_sec_level = get_int(&p, -1);
+    }
+    else
+        return;
+
+    if (le_rspndr_sec_level == 0)
+    {
+        le_coc_seclevel |= BTM_SEC_NONE;
+    }
+    else if (le_rspndr_sec_level == 1)
+    {
+        le_coc_seclevel |= BTM_SEC_IN_AUTHENTICATE;
+    }
+    else if (le_rspndr_sec_level == 2)
+    {
+        le_coc_seclevel |= BTM_SEC_IN_ENCRYPT;
+        le_coc_seclevel |= BTM_SEC_IN_AUTHENTICATE;
+    }
+    else
+    {
+        printf("Security level not supported");
+        return ;
+    }
+    printf("g_SecLevel = %d \n", le_coc_seclevel);
+
+    sL2capInterface->RegisterLePsm(le_conn_info->loc_conn_info.le_psm, FALSE,
+                                           le_coc_seclevel, g_BleEncKeySize);
+
+    printf("Waiting for Incoming connection for LE PSM %d... \n",
+                              le_conn_info->loc_conn_info.le_psm);
+}
+
+UINT8 do_l2cap_DataWrite(UINT16 chnl_id, char *p , UINT32 len)
+{
+    return sL2capInterface->DataWrite(chnl_id, p, len);
+}
+
+static int send_file(char *p)
+{
+    uint32_t seq = 0, itration = 1;
+    int fd, size;
+    char filename[] = {0};
+    char tmpBuf[LE_ACL_MAX_BUFF_SIZE];
+    UINT16 lcid;
+
+    lcid = get_int(&p, -1);
+    t_le_chnl_info *le_conn_info = le_get_conn_info_by_lcid(lcid);
+    GetFileName(p, filename);
+
+    if(!le_conn_info)
+    {
+        printf("No conn info, exit \n");
+        return FALSE;
+    }
+
+    g_omtu =  le_conn_info->rmt_conn_info.le_mtu;
+
+    if(g_omtu < LE_ACL_MAX_BUFF_SIZE)
+        data_size = g_omtu;
+    else
+        data_size = LE_ACL_MAX_BUFF_SIZE;
+
+    printf("data_size(max patload size) = %ld, g_omtu(max ttansmission unit) = %d",
+            data_size, g_omtu);
+
+    printf("Filename for input data = %s \n", filename);
+
+    if ((fd = open(filename, O_RDONLY)) < 0)
+    {
+        printf("Open failed: %s (%d)\n", strerror(errno), errno);
+        exit(1);
+    }
+    while (1)
+    {
+        while(cong_status)
+        {
+            usleep(50 * 1000);
+        }
+        if((size = read(fd, tmpBuf, data_size)) <= 0)
+        {
+            printf("\n File end ");
+            break;
+        }
+        printf("Sending data :: itration %d, omtu %d, writing data size %d\n",
+                itration, g_omtu, size);
+        do_l2cap_DataWrite(lcid, tmpBuf, size);
+        itration++;
+    }
+
+    if (num_frames && g_delay && count && !(seq % count))
+        usleep(g_delay);
+    return TRUE;
+}
+
+static int Send_Data(char *p)
+{
+    //uint32_t seq =0;
+    int send_mode;
+    UINT16 lcid;
+
+    lcid = get_int(&p, -1);
+    send_mode = get_int(&p, -1);
+
+    char tmpBuffer_1[] = {
+        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+        0x7F
+    };
+    char tmpBuffer_2[] = {
+        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+        0x7F,0x7F,0x7F
+    };
+
+    if(send_mode == 1)  // segmented
+    {
+        printf("Sending Segmented data...\nData written len %d...\n",
+                sizeof(tmpBuffer_1) );
+        do_l2cap_DataWrite(lcid, tmpBuffer_1, sizeof(tmpBuffer_1));
+    }
+    else if( send_mode == 0) // unsegmented
+    {
+        printf("Sending Unsegmented data...\nData written len %d...\n",
+                sizeof(tmpBuffer_2) );
+        do_l2cap_DataWrite(lcid, tmpBuffer_2, sizeof(tmpBuffer_2));
+    }
+    return TRUE;
+}
+
+static void send_data_on_le_coc(char *svr)
+{
+    printf("Sending data on LE L2CAP CoC...\n");
+    Send_Data(svr);
+}
+static void do_send_file(char *svr)
+{
+    printf("Sending file on LE L2CAP CoC...\n");
+    send_file(svr);
+}
+
+BOOLEAN le_coc_disc(char *p)
+{
+    UINT16 cid = get_int(&p, -1);
+    return sL2capInterface->DisconnectReq(cid);
+}
+
+static void do_le_coc_disconnect(char *p)
+{
+    le_coc_disc(p);
+}
+
+/*******************************************************************************
+ ** SMP API commands
+ *******************************************************************************/
+void do_smp_init(char *p)
+{
+    sSmpIface->init();
+    sleep(1);
+    sSmpIface->Register(SMP_cb);
+    sleep(1);
+}
+
+void do_smp_pair(char *p)
+{
+    tSMP_STATUS Ret = 0;
+    bt_bdaddr_t bd_addr = {{0}};
+    if(FALSE == GetBdAddr(p, &bd_addr))    return;
+    Ret = sSmpIface->Pair(bd_addr.address);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+
+void do_smp_pair_cancel(char *p)
+{
+    BOOLEAN Ret = 0;
+    bt_bdaddr_t bd_addr = {{0}};
+    if(FALSE == GetBdAddr(p, &bd_addr))    return;
+    Ret = sSmpIface->PairCancel(bd_addr.address);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+
+void do_smp_security_grant(char *p)
+{
+    UINT8    res;
+    bt_bdaddr_t bd_addr = {{0}};
+    if(FALSE == GetBdAddr(p, &bd_addr))    return; //arg1
+    res = get_int(&p, -1); // arg2
+    sSmpIface->SecurityGrant(bd_addr.address, res);
+    printf("%s:: Ret=%d \n", __FUNCTION__,res);
+}
+
+void do_smp_passkey_reply(char *p)
+{
+    UINT32 passkey;
+    UINT8    res;
+    bt_bdaddr_t bd_addr = {{0}};
+    if(FALSE == GetBdAddr(p, &bd_addr))    return; //arg1
+        printf("get res value\n");
+    res = get_int(&p, -1); // arg2
+        printf("res value=%d\n", res);
+    passkey = get_int(&p, -1); // arg3
+        printf("passkey value=%d\n", passkey);
+    sSmpIface->PasskeyReply(bd_addr.address, res, passkey);
+    printf("%s:: Ret=%d \n", __FUNCTION__,res);
+}
+
+void do_smp_encrypt(char *p)
+{
+    BOOLEAN Ret = 0;
+    UINT8    res;
+    bt_bdaddr_t bd_addr = {{0}};
+    if(FALSE == GetBdAddr(p, &bd_addr))    return; //arg1
+    res = get_int(&p, -1); // arg2
+    printf("%s:: res =%d Ret=%d \n", __FUNCTION__,res, Ret);
+}
+
+void do_le_gap_conn_param_update(char *p)
+{
+    //attr_uuid = get_int(&p, -1);
+    tGAP_BLE_ATTR_VALUE attr_value;
+    attr_value.conn_param.int_min = 50;
+    attr_value.conn_param.int_max = 70;
+    attr_value.conn_param.latency = 0;
+    attr_value.conn_param.sp_tout = 10;
+    bt_bdaddr_t bd_addr = {{0}};
+    if(FALSE == GetBdAddr(p, &bd_addr))    return; //arg1
+    //attr_uuid = get_hex(&p, -1);
+    //L2CA_UpdateBleConnParams(bd_addr.address, 50, 70, 0, 1000);
+    printf("stage 1\n");
+    sGapInterface->Gap_BleAttrDBUpdate(bd_addr.address, attr_value.conn_param.int_min, attr_value.conn_param.int_max,attr_value.conn_param.latency ,attr_value.conn_param.sp_tout);
+    printf("%s:: GAP connection parameter Update\n", __FUNCTION__);
+
+}
+void do_le_gap_attr_init(char *p)
+{
+    sGapInterface->Gap_AttrInit();
+    printf("%s:: GAP Initialization\n", __FUNCTION__);
+
+}
+/*
+void do_le_gap_set_disc(char *p)
+{
+    UINT16 Ret = 0;
+    UINT16 mode;
+    UINT16 duration;
+    UINT16 interval;
+
+    mode = get_int(&p, -1);
+    if(1 == mode)         mode = GAP_NON_DISCOVERABLE;
+    else if(2 == mode)  mode = GAP_LIMITED_DISCOVERABLE;
+    else                mode = GAP_GENERAL_DISCOVERABLE;
+
+    duration = get_int(&p, -1);
+    if((12 > duration) || (duration > 1000))    duration = 0; //if 0 is passed, stack will take 12 as default
+
+    interval = get_int(&p, -1);
+    if((12 > interval) || (interval > 1000))    interval = 0; //if 0 is passed, stack will take 800 as default
+
+
+
+    sGapInterface->Gap_SetDiscoverableMode(mode, duration, interval);
+    printf("%s:: Ret=%d\n", __FUNCTION__, Ret);
+}
+
+void do_le_gap_set_conn(char *p)
+{
+    UINT16 Ret=0;
+    UINT16 mode;
+    UINT16 duration;
+    UINT16 interval;
+
+    mode = get_int(&p, -1);
+    if(1 == mode)
+           mode = GAP_NON_CONNECTABLE;
+    else
+           mode = GAP_CONNECTABLE;
+
+    duration = get_int(&p, -1);
+        if((12 > duration) || (duration > 1000))    duration = 0; //if 0 is passed, stack will take 12 as default
+
+    interval = get_int(&p, -1);
+    if((12 > interval) || (interval > 1000))    interval = 0; //if 0 is passed, stack will take 800 as default
+
+    sGapInterface->Gap_SetConnectableMode(mode, duration, interval);
+    printf("%s:: Ret=%d\n", __FUNCTION__, Ret);
+}
+*/
+void do_l2cap_send_data_cid(char *p)
+{
+    UINT16        cid        = 0;
+    BT_HDR        bt_hdr;
+    UINT16         Ret = 0;
+    bt_bdaddr_t bd_addr = {{0}};
+    if(FALSE == GetBdAddr(p, &bd_addr))    return; //arg1
+    cid = get_int(&p, -1); // arg2
+
+    bt_hdr.event     = 0;
+    bt_hdr.len         = 1;
+    bt_hdr.offset     = 0;
+    bt_hdr.layer_specific = 0;
+
+
+    Ret = sL2capInterface->SendFixedChnlData(cid, bd_addr.address, &bt_hdr);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+
+}
+/*******************************************************************
+ *
+ *  CONSOLE COMMAND TABLE
+ *
+*/
+
+const t_cmd console_cmd_list[] =
+{
+    /*
+     * INTERNAL
+     */
+
+    { "help", do_help, "lists all available console commands", 0 },
+    { "quit", do_quit, "", 0},
+
+    /*
+     * API CONSOLE COMMANDS
+     */
+
+     /* Init and Cleanup shall be called automatically */
+    { "enable", do_enable, ":: enables bluetooth", 0 },
+    { "disable", do_disable, ":: disables bluetooth", 0 },
+    { "dut_mode_configure", do_dut_mode_configure, ":: DUT mode - 1 to enter,0 to exit", 0 },
+    { "c_register", do_le_client_register, "::UUID: 1<1111..> 2<12323..> 3<321111..>", 0 },
+    { "c_deregister", do_le_client_deregister, "::UUID: 1<1111..> 2<12323..> 3<321111..>", 0 },
+    { "c_connect", do_le_client_connect, ":: transport-type<0,1...> , BdAddr<00112233445566>", 0 },
+    { "c_refresh", do_le_client_refresh, ":: BdAddr<00112233445566>", 0 },
+    { "c_conn_param_update", do_le_conn_param_update, ":: int min_interval, int max_interval,int latency, BdAddr<00112233445566>", 0 },
+    { "c_connect_auto", do_le_client_connect_auto, ":: BdAddr<00112233445566>", 0 },
+    { "c_disconnect", do_le_client_disconnect, ":: BdAddr<00112233445566>", 0 },
+    { "c_configureMTU", do_le_client_configureMTU, ":: 23", 0 },
+    { "c_discover", do_le_client_discover, "type(1-PrimaryService, 2-PrimaryService using UUID, 3-Included Service, 4-Characteristic, 5-Characteristic Descriptor) \
+                                            \n\t s.handle(hex) e.handle(hex) UUIDLen(16/32/128) UUID(hex)", 0 },
+    { "c_read", do_le_client_read, "Type(1-ByType, 2-ByHandle, 3-ByMultiple, 4-CharValue, 5-Partial (blob)) Auth_Req \
+                                    \n\t ByType       :: s.handle(hex) e.handle(hex) UUIDLen(16/32/128) UUID(hex) \
+                                    \n\t ByHandle     :: Handle(hex) \
+                                    \n\t ByMultiple   :: NumOfHandle<1-10> Handle_1(hex) Handle_2(hex) ... Handle_N(hex) \
+                                    \n\t CharValue    :: s.handle(hex) e.handle(hex) UUIDLen(16/32/128) UUID(hex) \
+                                    \n\t Partial/Blob :: Handle(hex) Offset(hex)", 0 },
+    { "c_write", do_le_client_write, "Type(1-No response, 2-write, 3-prepare write), Auth_req, Handle, Offset, Len(0-600), Value(hex)", 0 },
+    { "c_execute_write", do_le_execute_write, "is_execute", 0 },
+    { "c_scan_start", do_le_client_scan_start, "::", 0 },
+    { "c_scan_stop", do_le_client_scan_stop, "::", 0 },
+    { "c_listen_start", do_le_client_listen_start, "::", 0 },
+    { "c_listen_stop", do_le_client_listen_stop, "::", 0 },
+    { "c_set_adv_mode", do_le_client_set_adv_mode, ":: Discoverability mode,Connectable_mode,", 0 },
+    { "c_set_adv_data", do_le_client_set_adv_data, "::EnableScanrsp<0/1>, IncludeName<0/1> IncludeTxPower<0/1>,min_conn_interval,int  max_conn_interval", 0 },
+    { "c_set_multi_adv_data", do_le_client_multi_adv_set_inst_data, "::EnableScanrsp<0/1>, IncludeName<0/1> IncludeTxPower<0/1>", 0 },
+    { "start_advertising", do_le_client_adv_enable, "::int client_if,int min_interval,int max_interval,int adv_type,int chnl_map, int tx_power timeout",0},
+    { "c_adv_update", do_le_client_adv_update, "::int client_if, int min_interval,int max_interval,int adv_type,int chnl_map, int tx_power, int timeout",0},
+    { "stop_advertising", do_le_client_adv_disable, "::int adv_if",0},
+    { "c_set_idle_timeout", do_le_set_idle_timeout, "bd_addr, time_out(int)", 0 },
+    { "c_gap_attr_init", do_le_gap_attr_init, "::", 0 },
+    { "c_gap_conn_param_update", do_le_gap_conn_param_update, "::", 0 },
+
+    { "s_register", do_le_server_register, "::UUID: 1<1111..> 2<12323..> 3<321111..>", 0 },
+    { "s_connect", do_le_server_connect, ":: BdAddr<00112233445566>", 0 },
+    { "s_connect_auto", do_le_server_connect_auto, ":: BdAddr<00112233445566>", 0 },
+    { "s_disconnect", do_le_server_disconnect, ":: BdAddr<00112233445566>", 0 },
+    { "s_add_service", do_le_server_add_service, "::", 0 },
+
+    { "pair", do_pairing, ":: BdAddr<00112233445566>", 0 },
+
+    { "smp_init", do_smp_init, "::", 0 }, //Here itself we will register.
+    { "smp_pair", do_smp_pair, ":: BdAddr<00112233445566>", 0 },
+    { "smp_pair_cancel", do_smp_pair_cancel, ":: BdAddr<00112233445566>", 0 },
+    { "smp_security_grant", do_smp_security_grant, ":: BdAddr<00112233445566>, res<>", 0 },
+    { "smp_passkey_reply", do_smp_passkey_reply, ":: BdAddr<00112233445566>, res<>, passkey<>", 0 },
+    //{ "smp_encrypt", do_smp_encrypt, "::", 0 },
+    { "l2cap_send_data_cid", do_l2cap_send_data_cid, ":: BdAddr<00112233445566>, CID<>", 0 },
+
+    { "set_local_name", do_set_localname, ":: setName<name>", 0 },
+    /* LE-L2CAP cmds */
+    { " ", NULL, "\n\t\t\033[0m\033[34mLE L2CAP CoC Commands\033[0m", 0 },
+    { " ", NULL, "\033[0m\033[34mCommands\t\t\tParameters\033[0m", 0 },
+
+    { "start_adv", do_start_advertisment, "\t\t::\tuuid [0 - register"\
+        "none (or) 1 - register uuid] , \n\t\t\t\tflag [0- stop adv (or) "\
+        "1 - start adv] \n  " , 0},
+
+    { "le_l2cap_listen", le_l2cap_listen, "\t::\tle_psm [1 to 255], "\
+        "\n\t\t\t\tle_mtu [23 to 65535], \n\t\t\t\tle_mps [23 to 65533],"\
+        " \n\t\t\t\tinit_credits [0 to 65535], \n\t\t\t\tsec_level "\
+        "[0 - None, 1 - Authentication, 2 - Auth and Encryption]", 0},
+
+    { "le_l2cap_coc_connect", le_l2cap_coc_connect, "\t::\tle_psm [128 to 255],"\
+        "\n\t\t\t\tle_mtu [23 to 65535], \n\t\t\t\tle_mps [23 to 65533], "\
+        "\n\t\t\t\tinit_credits [0 to 65535], \n\t\t\t\tsec_level [0 - None,"\
+        " 1 - Authentication, 2 - Encryption], \n\t\t\t\tbd_addr [001122334455] ", 0},
+
+    { "le_l2cap_coc_flow_ctrl", le_l2cap_coc_flow_ctrl, "\t::\tchnl_id [chnl id"\
+        "info from conn_ind or conn_cnf], \n\t\t\t\tcredits [1 to 65535]", 0},
+
+    { "send_data_on_le_coc", send_data_on_le_coc, "\t::\tchnl_id [chnl id info "\
+        "from conn_ind or conn_cnf] , \n\t\t\t\tdata_type [0 - Unsegmented data ,"\
+        "1 - Segmented data]", 0},
+
+    { "send_file", do_send_file, "\t\t::\tchnl_id [chnl_id info from conn_ind"\
+        "or conn_cnf], \n\t\t\t\tfile_name", 0},
+
+    { "le_coc_disconnect", do_le_coc_disconnect, "\t::\tchnl_id [chnl_id info"\
+        "from conn_ind or conn_cnf]", 0},
+    /* add here */
+
+    /* last entry */
+    {NULL, NULL, "", 0},
+};
+
+/*
+ * Main console command handler
+*/
+
+static void process_cmd(char *p, unsigned char is_job)
+{
+    char cmd[2048];
+    int i = 0;
+    bt_pin_code_t pincode;
+    char *p_saved = p;
+
+    get_str(&p, cmd);
+
+    /* table commands */
+    while (console_cmd_list[i].name != NULL)
+    {
+        if (is_cmd(console_cmd_list[i].name))
+        {
+            if (!is_job && console_cmd_list[i].is_job)
+                create_cmdjob(p_saved);
+            else
+            {
+                console_cmd_list[i].handler(p);
+            }
+            return;
+        }
+        i++;
+    }
+    //pin key
+    if(cmd[6] == '.') {
+        for(i=0; i<6; i++) {
+            pincode.pin[i] = cmd[i];
+        }
+        pincode.pin[i] = '\0';
+        if(BT_STATUS_SUCCESS != sBtInterface->pin_reply(remote_bd_address, TRUE, strlen((const char*)pincode.pin), &pincode)) {
+            printf("Pin Reply failed\n");
+        }
+        else
+            printf("Pin Reply done and paired\n");
+        //flush the char for pinkey
+        cmd[6] = 0;
+    }
+    else {
+        bdt_log("%s : unknown command\n", p_saved);
+        do_help(NULL);
+    }
+}
+
+int main (int argc, char * argv[])
+{
+    static btgatt_callbacks_t    sGatt_cb = {sizeof(btgatt_callbacks_t), &sGattClient_cb, &sGattServer_cb};
+
+    config_permissions();
+    bdt_log("\n:::::::::::::::::::::::::::::::::::::::::::::::::::");
+    bdt_log(":: Bluedroid test app starting");
+
+    if ( HAL_load() < 0 ) {
+        perror("HAL failed to initialize, exit\n");
+        unlink(PID_FILE);
+        exit(0);
+    }
+
+    setup_test_env();
+
+    /* Automatically perform the init */
+    bdt_init();
+    sleep(5);
+    bdt_enable();
+    sleep(5);
+    bdt_log("Get SMP IF BT Interface = %x \n", sBtInterface);
+    sGattInterface   = sBtInterface->get_testapp_interface(TEST_APP_GATT);
+    sSmpIface        = sBtInterface->get_testapp_interface(TEST_APP_SMP);
+    bdt_log("Get GAP IF");
+    sGapInterface    = sBtInterface->get_testapp_interface(TEST_APP_GAP);
+
+    bdt_log("Get GATT IF");
+    sGattIfaceScan     = sBtInterface->get_profile_interface(BT_PROFILE_GATT_ID);
+
+    bdt_log("Get L2CAP IF");
+    sL2capInterface        = sBtInterface->get_testapp_interface(TEST_APP_L2CAP);
+
+    sGattIfaceScan->init(&sGatt_cb);
+    bdt_log("GATT IF INIT Done");
+
+    printf("\n Before l2cap init\n");
+    do_l2cap_init(NULL);
+    printf("\n after l2cap init\n");
+
+    while(!main_done)
+    {
+        char line[2048];
+
+        /* command prompt */
+        printf( ">" );
+        fflush(stdout);
+
+        fgets (line, 2048, stdin);
+
+        if (line[0]!= '\0')
+        {
+            /* remove linefeed */
+            line[strlen(line)-1] = 0;
+
+            process_cmd(line, 0);
+            memset(line, '\0', 2048);
+        }
+    }
+
+    /* FIXME: Commenting this out as for some reason, the application does not exit otherwise*/
+    //bdt_cleanup();
+
+    HAL_unload();
+
+    bdt_log(":: Bluedroid test app terminating");
+
+    return 0;
+}
+int GetFileName(char *p, char *filename)
+{
+//    uint8_t  i;
+    int len;
+
+    skip_blanks(&p);
+
+    printf("Input file name = %s\n", p);
+
+    if (p == NULL)
+    {
+        printf("\nInvalid File Name... Please enter file name\n");
+        return FALSE;
+    }
+    len = strlen(p);
+
+    memcpy(filename, p, len);
+    filename[len] = '\0';
+
+    return TRUE;
+}
+int GetBdAddr(char *p, bt_bdaddr_t *pbd_addr)
+{
+    char Arr[13] = {0};
+    char *pszAddr = NULL;
+    uint8_t k1 = 0;
+    uint8_t k2 = 0;
+    uint8_t  i;
+
+    skip_blanks(&p);
+
+    printf("Input=%s\n", p);
+
+    if(12 > strlen(p))
+    {
+        printf("\nInvalid Bd Address. Format[112233445566]\n");
+        return FALSE;
+    }
+    memcpy(Arr, p, 12);
+
+    for(i=0; i<12; i++)
+    {
+        Arr[i] = tolower(Arr[i]);
+    }
+    pszAddr = Arr;
+
+    for(i=0; i<6; i++)
+    {
+        k1 = (uint8_t) ( (*pszAddr >= 'a') ? ( 10 + (uint8_t)( *pszAddr - 'a' )) : (*pszAddr - '0') );
+        pszAddr++;
+        k2 = (uint8_t) ( (*pszAddr >= 'a') ? ( 10 + (uint8_t)( *pszAddr - 'a' )) : (*pszAddr - '0') );
+        pszAddr++;
+
+        if ( (k1>15)||(k2>15) )
+        {
+            return FALSE;
+        }
+        pbd_addr->address[i] = (k1<<4 | k2);
+    }
+    return TRUE;
+}
+#endif //TEST_APP_INTERFACE
diff --git a/test/bluedroidtest/Android.mk b/test/bluedroidtest/Android.mk
new file mode 100644
index 0000000..aeea6fa
--- /dev/null
+++ b/test/bluedroidtest/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=     \
+    bluedroidtest.c
+
+LOCAL_C_INCLUDES :=
+LOCAL_CFLAGS := -Wno-unused-parameter
+
+LOCAL_CFLAGS += -std=c99
+
+LOCAL_CFLAGS += -std=c99
+
+LOCAL_MODULE_TAGS := debug optional
+
+LOCAL_MODULE:= bdt
+
+LOCAL_SHARED_LIBRARIES += libcutils   \
+                          libhardware \
+                          libhardware_legacy
+
+LOCAL_MULTILIB := 32
+
+include $(BUILD_EXECUTABLE)
diff --git a/test/bluedroidtest/README.txt b/test/bluedroidtest/README.txt
new file mode 100644
index 0000000..0a47050
--- /dev/null
+++ b/test/bluedroidtest/README.txt
@@ -0,0 +1,88 @@
+Bluedroid Test Application
+==========================
+The test application provides a small console shell interface that allows
+access to the Bluetooth HAL API library though ASCII commands. This is similar
+to how the real JNI service would operate. The primary objective of this
+application is to allow Bluetooth to be put in DUT Mode for RF/BB BQB test purposes.
+
+This application is mutually exclusive with the Java based Bluetooth.apk. Hence
+before launching the application, it should be ensured that the Settings->Bluetooth is OFF.
+
+This application is built as 'bdt' and shall be available in '/system/bin/bdt'
+
+Limitations
+===========
+1.) Settings->Bluetooth must be OFF for this application to work
+2.) Currently, only the SIG 'HCI Test Mode' commands are supported. The vendor
+specific HCI test mode commands to be added.
+
+Usage instructions
+==================
+The following section describes the various commands and their usage
+
+Launching the test application
+==============================
+$ adb shell
+root@android:/ # /system/bin/bdt
+set_aid_and_cap : pid 1183, uid 0 gid 0
+:::::::::::::::::::::::::::::::::::::::::::::::::::
+:: Bluedroid test app starting
+Loading HAL lib + extensions
+HAL library loaded (Success)
+INIT BT
+HAL REQUEST SUCCESS
+
+Enabling Bluetooth
+==================
+>enable
+ENABLE BT
+HAL REQUEST SUCCESS
+>ADAPTER STATE UPDATED : ON
+
+Enabling Test Mode (Bluetooth must be enabled for this command to work)
+======================================================================
+>dut_mode_configure 1
+BT DUT MODE CONFIGURE
+HAL REQUEST SUCCESS
+>
+
+Disabling Test Mode
+===================
+>dut_mode_configure 0
+BT DUT MODE CONFIGURE
+HAL REQUEST SUCCESS
+>
+
+Running BLE Test commands (Bluetooth must be enabled)
+=====================================================
+NOTE: Unlike BR/EDR, there is no explicit DUT mode to run these BLE tests.
+
+> le_test_mode 1 <rx_freq>
+
+> le_test_mode 2 <tx_freq> <test_data_len> <payload_pattern>
+
+> le_test_mode 3 <no_args>
+Please refer to the BT Core spec pages-1099 to 1102 for possible values for
+the above parameters. These values need to be provided in Decimal format.
+
+Exit the test application
+=========================
+>quit
+shutdown bdroid test app
+Unloading HAL lib
+HAL library unloaded (Success)
+:: Bluedroid test app terminating
+
+Help (Lists the available commands)
+===================================
+>help
+help lists all available console commands
+
+quit
+enable :: enables bluetooth
+disable :: disables bluetooth
+dut_mode_configure :: DUT mode - 1 to enter,0 to exit
+le_test_mode :: LE Test Mode - RxTest - 1 <rx_freq>,
+	                           TxTest - 2 <tx_freq> <test_data_len> <payload_pattern>,
+	                           End Test - 3 <no_args>
+
diff --git a/test/bluedroidtest/bluedroidtest.c b/test/bluedroidtest/bluedroidtest.c
new file mode 100644
index 0000000..114ec0b
--- /dev/null
+++ b/test/bluedroidtest/bluedroidtest.c
@@ -0,0 +1,937 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/************************************************************************************
+ *
+ *  Filename:      bluedroidtest.c
+ *
+ *  Description:   Bluedroid Test application
+ *
+ ***********************************************************************************/
+
+#include <stdio.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/prctl.h>
+#include <sys/capability.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <private/android_filesystem_config.h>
+#include <android/log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/bluetooth.h>
+
+/************************************************************************************
+**  Constants & Macros
+************************************************************************************/
+
+#define PID_FILE "/data/.bdt_pid"
+#define DEVICE_DISCOVERY_TIMEOUT 20
+
+#ifndef MAX
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+#endif
+
+#define CASE_RETURN_STR(const) case const: return #const;
+
+#define UNUSED __attribute__((unused))
+
+/************************************************************************************
+**  Local type definitions
+************************************************************************************/
+
+/************************************************************************************
+**  Static variables
+************************************************************************************/
+
+static unsigned char main_done = 0;
+static bt_status_t status;
+
+/* Main API */
+static bluetooth_device_t* bt_device;
+
+const bt_interface_t* sBtInterface = NULL;
+
+static gid_t groups[] = { AID_NET_BT, AID_INET, AID_NET_BT_ADMIN,
+                          AID_SYSTEM, AID_MISC, AID_SDCARD_RW,
+                          AID_NET_ADMIN, AID_VPN};
+
+/* Set to 1 when the Bluedroid stack is enabled */
+static unsigned char bt_enabled = 0;
+static int deviceCount;
+static int wantMore = 0;
+pthread_mutex_t deviceCount_mutex;
+pthread_cond_t deviceCount_cond;
+
+/************************************************************************************
+**  Static functions
+************************************************************************************/
+
+static void process_cmd(char *p, unsigned char is_job);
+static void job_handler(void *param);
+static void bdt_log(const char *fmt_str, ...);
+static void discover_device(void *arg);
+
+
+/************************************************************************************
+**  Externs
+************************************************************************************/
+
+/************************************************************************************
+**  Functions
+************************************************************************************/
+
+
+/************************************************************************************
+**  Shutdown helper functions
+************************************************************************************/
+
+static void bdt_shutdown(void)
+{
+    bdt_log("shutdown bdroid test app\n");
+    main_done = 1;
+}
+
+
+/*****************************************************************************
+** Android's init.rc does not yet support applying linux capabilities
+*****************************************************************************/
+
+static void config_permissions(void)
+{
+    struct __user_cap_header_struct header;
+    struct __user_cap_data_struct cap[2];
+
+    bdt_log("set_aid_and_cap : pid %d, uid %d gid %d", getpid(), getuid(), getgid());
+
+    header.pid = 0;
+
+    prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+
+    setuid(AID_BLUETOOTH);
+    setgid(AID_BLUETOOTH);
+
+    header.version = _LINUX_CAPABILITY_VERSION_3;
+
+    cap[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW);
+    cap[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN);
+    cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].permitted |= CAP_TO_MASK(CAP_NET_BIND_SERVICE);
+    cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].permitted |= CAP_TO_MASK(CAP_SYS_RAWIO);
+    cap[CAP_TO_INDEX(CAP_SYS_NICE)].permitted |= CAP_TO_MASK(CAP_SYS_NICE);
+    cap[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
+    cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].permitted |= CAP_TO_MASK(CAP_WAKE_ALARM);
+
+    cap[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW);
+    cap[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN);
+    cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].effective |= CAP_TO_MASK(CAP_NET_BIND_SERVICE);
+    cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].effective |= CAP_TO_MASK(CAP_SYS_RAWIO);
+    cap[CAP_TO_INDEX(CAP_SYS_NICE)].effective |= CAP_TO_MASK(CAP_SYS_NICE);
+    cap[CAP_TO_INDEX(CAP_SETGID)].effective |= CAP_TO_MASK(CAP_SETGID);
+    cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].effective |= CAP_TO_MASK(CAP_WAKE_ALARM);
+
+    capset(&header, &cap[0]);
+    setgroups(sizeof(groups)/sizeof(groups[0]), groups);
+}
+
+
+
+/*****************************************************************************
+**   Logger API
+*****************************************************************************/
+
+void bdt_log(const char *fmt_str, ...)
+{
+    static char buffer[1024];
+    va_list ap;
+
+    va_start(ap, fmt_str);
+    vsnprintf(buffer, 1024, fmt_str, ap);
+    va_end(ap);
+
+    fprintf(stdout, "%s\n", buffer);
+}
+
+/*******************************************************************************
+ ** Misc helper functions
+ *******************************************************************************/
+static const char* dump_bt_status(bt_status_t status)
+{
+    switch(status)
+    {
+        CASE_RETURN_STR(BT_STATUS_SUCCESS)
+        CASE_RETURN_STR(BT_STATUS_FAIL)
+        CASE_RETURN_STR(BT_STATUS_NOT_READY)
+        CASE_RETURN_STR(BT_STATUS_NOMEM)
+        CASE_RETURN_STR(BT_STATUS_BUSY)
+        CASE_RETURN_STR(BT_STATUS_UNSUPPORTED)
+
+        default:
+            return "unknown status code";
+    }
+}
+
+static void hex_dump(char *msg, void *data, int size, int trunc)
+{
+    unsigned char *p = data;
+    unsigned char c;
+    int n;
+    char bytestr[4] = {0};
+    char addrstr[10] = {0};
+    char hexstr[ 16*3 + 5] = {0};
+    char charstr[16*1 + 5] = {0};
+
+    bdt_log("%s  \n", msg);
+
+    /* truncate */
+    if(trunc && (size>32))
+        size = 32;
+
+    for(n=1;n<=size;n++) {
+        if (n%16 == 1) {
+            /* store address for this line */
+            snprintf(addrstr, sizeof(addrstr), "%.4x",
+               (unsigned int)((uintptr_t)p-(uintptr_t)data) );
+        }
+
+        c = *p;
+        if (isalnum(c) == 0) {
+            c = '.';
+        }
+
+        /* store hex str (for left side) */
+        snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
+        strlcat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
+
+        /* store char str (for right side) */
+        snprintf(bytestr, sizeof(bytestr), "%c", c);
+        strlcat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
+
+        if(n%16 == 0) {
+            /* line completed */
+            bdt_log("[%4.4s]   %-50.50s  %s\n", addrstr, hexstr, charstr);
+            hexstr[0] = 0;
+            charstr[0] = 0;
+        } else if(n%8 == 0) {
+            /* half line: add whitespaces */
+            strlcat(hexstr, "  ", sizeof(hexstr)-strlen(hexstr)-1);
+            strlcat(charstr, " ", sizeof(charstr)-strlen(charstr)-1);
+        }
+        p++; /* next byte */
+    }
+
+    if (strlen(hexstr) > 0) {
+        /* print rest of buffer if not empty */
+        bdt_log("[%4.4s]   %-50.50s  %s\n", addrstr, hexstr, charstr);
+    }
+}
+
+/*******************************************************************************
+ ** Console helper functions
+ *******************************************************************************/
+
+void skip_blanks(char **p)
+{
+  while (**p == ' ')
+    (*p)++;
+}
+
+uint32_t get_int(char **p, int DefaultValue)
+{
+  uint32_t Value = 0;
+  unsigned char   UseDefault;
+
+  UseDefault = 1;
+  skip_blanks(p);
+
+  while ( ((**p)<= '9' && (**p)>= '0') )
+    {
+      Value = Value * 10 + (**p) - '0';
+      UseDefault = 0;
+      (*p)++;
+    }
+
+  if (UseDefault)
+    return DefaultValue;
+  else
+    return Value;
+}
+
+int get_signed_int(char **p, int DefaultValue)
+{
+  int    Value = 0;
+  unsigned char   UseDefault;
+  unsigned char  NegativeNum = 0;
+
+  UseDefault = 1;
+  skip_blanks(p);
+
+  if ( (**p) == '-')
+    {
+      NegativeNum = 1;
+      (*p)++;
+    }
+  while ( ((**p)<= '9' && (**p)>= '0') )
+    {
+      Value = Value * 10 + (**p) - '0';
+      UseDefault = 0;
+      (*p)++;
+    }
+
+  if (UseDefault)
+    return DefaultValue;
+  else
+    return ((NegativeNum == 0)? Value : -Value);
+}
+
+void get_str(char **p, char *Buffer)
+{
+  skip_blanks(p);
+
+  while (**p != 0 && **p != ' ')
+    {
+      *Buffer = **p;
+      (*p)++;
+      Buffer++;
+    }
+
+  *Buffer = 0;
+}
+
+uint32_t get_hex(char **p, int DefaultValue)
+{
+  uint32_t Value = 0;
+  unsigned char   UseDefault;
+
+  UseDefault = 1;
+  skip_blanks(p);
+
+  while ( ((**p)<= '9' && (**p)>= '0') ||
+          ((**p)<= 'f' && (**p)>= 'a') ||
+          ((**p)<= 'F' && (**p)>= 'A') )
+    {
+      if (**p >= 'a')
+        Value = Value * 16 + (**p) - 'a' + 10;
+      else if (**p >= 'A')
+        Value = Value * 16 + (**p) - 'A' + 10;
+      else
+        Value = Value * 16 + (**p) - '0';
+      UseDefault = 0;
+      (*p)++;
+    }
+
+  if (UseDefault)
+    return DefaultValue;
+  else
+    return Value;
+}
+
+void get_bdaddr(const char *str, bt_bdaddr_t *bd) {
+    char *d = ((char *)bd), *endp;
+    int i;
+    for(i = 0; i < 6; i++) {
+        *d++ = strtol(str, &endp, 16);
+        if (*endp != ':' && i != 5) {
+            memset(bd, 0, sizeof(bt_bdaddr_t));
+            return;
+        }
+        str = endp + 1;
+    }
+}
+
+#define is_cmd(str) ((strlen(str) == strlen(cmd)) && strncmp((const char *)&cmd, str, strlen(str)) == 0)
+#define if_cmd(str)  if (is_cmd(str))
+
+typedef void (t_console_cmd_handler) (char *p);
+
+typedef struct {
+    const char *name;
+    t_console_cmd_handler *handler;
+    const char *help;
+    unsigned char is_job;
+} t_cmd;
+
+
+const t_cmd console_cmd_list[];
+static int console_cmd_maxlen = 0;
+
+static void cmdjob_handler(void *param)
+{
+    char *job_cmd = (char*)param;
+
+    bdt_log("cmdjob starting (%s)", job_cmd);
+
+    process_cmd(job_cmd, 1);
+
+    bdt_log("cmdjob terminating");
+
+    free(job_cmd);
+}
+
+static int create_cmdjob(char *cmd)
+{
+    pthread_t thread_id;
+    char *job_cmd;
+
+    job_cmd = malloc(strlen(cmd)+1); /* freed in job handler */
+    if (job_cmd)
+    {
+        strlcpy(job_cmd, cmd, strlen(cmd)+1);
+
+        if (pthread_create(&thread_id, NULL,
+                       (void*)cmdjob_handler, (void*)job_cmd)!=0)
+        perror("pthread_create");
+    }
+    else
+    {
+        perror("create_cmdjob(): Failed to allocate memory");
+    }
+
+    return 0;
+}
+
+/*******************************************************************************
+ ** Load stack lib
+ *******************************************************************************/
+
+int HAL_load(void)
+{
+    int err = 0;
+
+    hw_module_t* module;
+    hw_device_t* device;
+
+    bdt_log("Loading HAL lib + extensions");
+
+    err = hw_get_module(BT_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
+    if (err == 0)
+    {
+        err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
+        if (err == 0) {
+            bt_device = (bluetooth_device_t *)device;
+            sBtInterface = bt_device->get_bluetooth_interface();
+        }
+    }
+
+    bdt_log("HAL library loaded (%s)", strerror(err));
+
+    return err;
+}
+
+int HAL_unload(void)
+{
+    int err = 0;
+
+    bdt_log("Unloading HAL lib");
+
+    sBtInterface = NULL;
+
+    bdt_log("HAL library unloaded (%s)", strerror(err));
+
+    return err;
+}
+
+/*******************************************************************************
+ ** HAL test functions & callbacks
+ *******************************************************************************/
+
+void setup_test_env(void)
+{
+    int i = 0;
+
+    while (console_cmd_list[i].name != NULL)
+    {
+        console_cmd_maxlen = MAX(console_cmd_maxlen, (int)strlen(console_cmd_list[i].name));
+        i++;
+    }
+}
+
+void check_return_status(bt_status_t status)
+{
+    if (status != BT_STATUS_SUCCESS)
+    {
+        bdt_log("HAL REQUEST FAILED status : %d (%s)", status, dump_bt_status(status));
+    }
+    else
+    {
+        bdt_log("HAL REQUEST SUCCESS");
+    }
+}
+
+static void adapter_state_changed(bt_state_t state)
+{
+    bdt_log("ADAPTER STATE UPDATED : %s", (state == BT_STATE_OFF)?"OFF":"ON");
+    if (state == BT_STATE_ON) {
+        bt_enabled = 1;
+    } else {
+        bt_enabled = 0;
+    }
+}
+
+static void dut_mode_recv(uint16_t UNUSED opcode, uint8_t UNUSED *buf, uint8_t UNUSED len)
+{
+    bdt_log("DUT MODE RECV : NOT IMPLEMENTED");
+}
+
+static void le_test_mode(bt_status_t status, uint16_t packet_count)
+{
+    bdt_log("LE TEST MODE END status:%s number_of_packets:%d", dump_bt_status(status), packet_count);
+}
+
+static void device_found_cb(int num_properties, bt_property_t *properties)
+{
+    int i;
+    for (i = 0; i < num_properties; i++)
+    {
+        if (properties[i].type == BT_PROPERTY_BDNAME)
+        {
+            bdt_log("Device name is : %s\n",
+                  (char*)properties[i].val);
+        }
+        if (properties[i].type == BT_PROPERTY_REMOTE_RSSI)
+        {
+            pthread_mutex_lock(&deviceCount_mutex);
+            deviceCount++;
+            bdt_log("Device RSSI VALUE is :%d\n",
+                   *(signed char*)properties[i].val);
+            if (deviceCount > 0 && wantMore == 0)
+            {
+                pthread_cond_signal(&deviceCount_cond);
+            }
+            pthread_mutex_unlock(&deviceCount_mutex);
+        }
+    }
+}
+
+static bt_callbacks_t bt_callbacks = {
+    sizeof(bt_callbacks_t),
+    adapter_state_changed,
+    NULL, /* adapter_properties_cb */
+    NULL, /* remote_device_properties_cb */
+    device_found_cb, /* device_found_cb */
+    NULL, /* discovery_state_changed_cb */
+    NULL, /* pin_request_cb  */
+    NULL, /* ssp_request_cb  */
+    NULL, /* bond_state_changed_cb */
+    NULL, /* acl_state_changed_cb */
+    NULL, /* thread_evt_cb */
+    dut_mode_recv, /* dut_mode_recv_cb */
+#if BLE_INCLUDED == TRUE
+    le_test_mode, /* le_test_mode_cb */
+#else
+    NULL, /* le_test_mode_cb */
+#endif
+    NULL, /* energy_info_cb */
+    NULL  /* hci_event_recv_cb */
+};
+
+static bool set_wake_alarm(uint64_t delay_millis, bool should_wake, alarm_cb cb, void *data) {
+  static timer_t timer;
+  static bool timer_created;
+
+  if (!timer_created) {
+    struct sigevent sigevent;
+    memset(&sigevent, 0, sizeof(sigevent));
+    sigevent.sigev_notify = SIGEV_THREAD;
+    sigevent.sigev_notify_function = (void (*)(union sigval))cb;
+    sigevent.sigev_value.sival_ptr = data;
+    timer_create(CLOCK_MONOTONIC, &sigevent, &timer);
+    timer_created = true;
+  }
+
+  struct itimerspec new_value;
+  new_value.it_value.tv_sec = delay_millis / 1000;
+  new_value.it_value.tv_nsec = (delay_millis % 1000) * 1000 * 1000;
+  new_value.it_interval.tv_sec = 0;
+  new_value.it_interval.tv_nsec = 0;
+  timer_settime(timer, 0, &new_value, NULL);
+
+  return true;
+}
+
+static int acquire_wake_lock(const char *lock_name) {
+  return BT_STATUS_SUCCESS;
+}
+
+static int release_wake_lock(const char *lock_name) {
+  return BT_STATUS_SUCCESS;
+}
+
+static bt_os_callouts_t callouts = {
+    sizeof(bt_os_callouts_t),
+    set_wake_alarm,
+    acquire_wake_lock,
+    release_wake_lock,
+};
+
+void bdt_init(void)
+{
+    bdt_log("INIT BT ");
+    status = sBtInterface->init(&bt_callbacks);
+
+    if (status == BT_STATUS_SUCCESS) {
+        status = sBtInterface->set_os_callouts(&callouts);
+    }
+
+    check_return_status(status);
+}
+
+void bdt_enable(void)
+{
+    bdt_log("ENABLE BT");
+    if (bt_enabled) {
+        bdt_log("Bluetooth is already enabled");
+        return;
+    }
+    status = sBtInterface->enable(false);
+
+    check_return_status(status);
+}
+
+void bdt_disable(void)
+{
+    bdt_log("DISABLE BT");
+    if (!bt_enabled) {
+        bdt_log("Bluetooth is already disabled");
+        return;
+    }
+    status = sBtInterface->disable();
+
+    check_return_status(status);
+}
+void bdt_dut_mode_configure(char *p)
+{
+    int32_t mode = -1;
+
+    bdt_log("BT DUT MODE CONFIGURE");
+    if (!bt_enabled) {
+        bdt_log("Bluetooth must be enabled for test_mode to work.");
+        return;
+    }
+    mode = get_signed_int(&p, mode);
+    if ((mode != 0) && (mode != 1)) {
+        bdt_log("Please specify mode: 1 to enter, 0 to exit");
+        return;
+    }
+    status = sBtInterface->dut_mode_configure(mode);
+
+    check_return_status(status);
+}
+
+#define HCI_LE_RECEIVER_TEST_OPCODE 0x201D
+#define HCI_LE_TRANSMITTER_TEST_OPCODE 0x201E
+#define HCI_LE_END_TEST_OPCODE 0x201F
+
+void bdt_le_test_mode(char *p)
+{
+    int cmd;
+    unsigned char buf[3];
+    int arg1, arg2, arg3;
+
+    bdt_log("BT LE TEST MODE");
+    if (!bt_enabled) {
+        bdt_log("Bluetooth must be enabled for le_test to work.");
+        return;
+    }
+
+    memset(buf, 0, sizeof(buf));
+    cmd = get_int(&p, 0);
+    switch (cmd)
+    {
+        case 0x1: /* RX TEST */
+           arg1 = get_int(&p, -1);
+           if (arg1 < 0) bdt_log("%s Invalid arguments", __FUNCTION__);
+           buf[0] = arg1;
+           status = sBtInterface->le_test_mode(HCI_LE_RECEIVER_TEST_OPCODE, buf, 1);
+           break;
+        case 0x2: /* TX TEST */
+            arg1 = get_int(&p, -1);
+            arg2 = get_int(&p, -1);
+            arg3 = get_int(&p, -1);
+            if ((arg1 < 0) || (arg2 < 0) || (arg3 < 0))
+                bdt_log("%s Invalid arguments", __FUNCTION__);
+            buf[0] = arg1;
+            buf[1] = arg2;
+            buf[2] = arg3;
+            status = sBtInterface->le_test_mode(HCI_LE_TRANSMITTER_TEST_OPCODE, buf, 3);
+           break;
+        case 0x3: /* END TEST */
+            status = sBtInterface->le_test_mode(HCI_LE_END_TEST_OPCODE, buf, 0);
+           break;
+        default:
+            bdt_log("Unsupported command");
+            return;
+            break;
+    }
+    if (status != BT_STATUS_SUCCESS)
+    {
+        bdt_log("%s Test 0x%x Failed with status:0x%x", __FUNCTION__, cmd, status);
+    }
+    return;
+}
+
+void bdt_cleanup(void)
+{
+    bdt_log("CLEANUP");
+    sBtInterface->cleanup();
+}
+
+/*******************************************************************************
+ ** Console commands
+ *******************************************************************************/
+
+void do_help(char UNUSED *p)
+{
+    int i = 0;
+    int max = 0;
+    char line[128];
+    int pos = 0;
+
+    while (console_cmd_list[i].name != NULL)
+    {
+        pos = sprintf(line, "%s", (char*)console_cmd_list[i].name);
+        bdt_log("%s %s\n", (char*)line, (char*)console_cmd_list[i].help);
+        i++;
+    }
+}
+
+void do_quit(char UNUSED *p)
+{
+    bdt_shutdown();
+}
+
+/*******************************************************************
+ *
+ *  BT TEST  CONSOLE COMMANDS
+ *
+ *  Parses argument lists and passes to API test function
+ *
+*/
+
+void do_init(char UNUSED *p)
+{
+    bdt_init();
+}
+
+void do_enable(char UNUSED *p)
+{
+    bdt_enable();
+}
+
+void do_disable(char UNUSED *p)
+{
+    bdt_disable();
+}
+void do_dut_mode_configure(char *p)
+{
+    bdt_dut_mode_configure(p);
+}
+
+void do_le_test_mode(char *p)
+{
+    bdt_le_test_mode(p);
+}
+
+void do_cleanup(char UNUSED *p)
+{
+    bdt_cleanup();
+}
+
+/*******************************************************************
+ *
+ *  CONSOLE COMMAND TABLE
+ *
+*/
+
+const t_cmd console_cmd_list[] =
+{
+    /*
+     * INTERNAL
+     */
+
+    { "help", do_help, "lists all available console commands", 0 },
+    { "quit", do_quit, "", 0},
+
+    /*
+     * API CONSOLE COMMANDS
+     */
+
+     /* Init and Cleanup shall be called automatically */
+    { "enable", do_enable, ":: enables bluetooth", 0 },
+    { "disable", do_disable, ":: disables bluetooth", 0 },
+    { "dut_mode_configure", do_dut_mode_configure, ":: DUT mode - 1 to enter,0 to exit", 0 },
+    { "le_test_mode", do_le_test_mode, ":: LE Test Mode - RxTest - 1 <rx_freq>, \n\t \
+                      TxTest - 2 <tx_freq> <test_data_len> <payload_pattern>, \n\t \
+                      End Test - 3 <no_args>", 0 },
+    /* add here */
+
+    /* last entry */
+    {NULL, NULL, "", 0},
+};
+
+/*
+ * Main console command handler
+*/
+
+static void process_cmd(char *p, unsigned char is_job)
+{
+    char cmd[64];
+    int i = 0;
+    char *p_saved = p;
+
+    get_str(&p, cmd);
+
+    /* table commands */
+    while (console_cmd_list[i].name != NULL)
+    {
+        if (is_cmd(console_cmd_list[i].name))
+        {
+            if (!is_job && console_cmd_list[i].is_job)
+                create_cmdjob(p_saved);
+            else
+            {
+                console_cmd_list[i].handler(p);
+            }
+            return;
+        }
+        i++;
+    }
+    bdt_log("%s : unknown command\n", p_saved);
+    do_help(NULL);
+}
+
+static void discover_device(void *arg)
+{
+    struct timespec ts = {0, 0};
+    ts.tv_sec = time(NULL) + DEVICE_DISCOVERY_TIMEOUT;
+
+    sBtInterface->start_discovery();
+    pthread_mutex_lock(&deviceCount_mutex);
+    pthread_cond_timedwait(&deviceCount_cond, &deviceCount_mutex, &ts);
+    if (deviceCount == 0)
+    {
+        bdt_log("No device found\n");
+    }
+    else
+    {
+        deviceCount = 0;
+    }
+    pthread_mutex_unlock(&deviceCount_mutex);
+    wantMore = 0;
+    bdt_log("Cancelling discovery\n");
+    sBtInterface->cancel_discovery();
+    pthread_exit(0);
+}
+
+int main (int UNUSED argc, char UNUSED *argv[])
+{
+    int opt;
+    char cmd[128];
+    int args_processed = 0;
+    int pid = -1;
+    int enable_wait_count = 0;
+    pthread_t discoveryThread;
+
+    config_permissions();
+    bdt_log("\n:::::::::::::::::::::::::::::::::::::::::::::::::::");
+    bdt_log(":: Bluedroid test app starting");
+
+    if ( HAL_load() < 0 ) {
+        perror("HAL failed to initialize, exit\n");
+        unlink(PID_FILE);
+        exit(0);
+    }
+
+    setup_test_env();
+    pthread_mutex_init(&deviceCount_mutex, NULL);
+    pthread_cond_init (&deviceCount_cond, NULL);
+
+    /* Automatically perform the init */
+    bdt_init();
+    if (argc > 1)
+    {
+        bdt_log("Command line mode\n");
+        if (strncmp(argv[1],"get_ap_list",11) == 0) {
+            wantMore = 1;
+        } else if (strncmp(argv[1],"get_a_device",12) == 0) {
+            wantMore = 0;
+        } else {
+             bdt_log("Unrecognised command");
+             goto cleanup;
+        }
+        bdt_log("Enabling BT for 45 seconds\n");
+        bdt_enable();
+        do {
+            if (bt_enabled)
+                break;
+                bdt_log("Waiting for bt_enabled to become true\n");
+                sleep(2);
+        } while(enable_wait_count++ < 10);
+
+        if (bt_enabled) {
+            pthread_create(&discoveryThread, NULL, (void*)discover_device, NULL);
+            pthread_join(discoveryThread, NULL);
+        } else {
+            bdt_log("Failed to enable BT\n");
+            goto cleanup;
+        }
+        bdt_log("Disabling BT\n");
+        bdt_disable();
+        goto cleanup;
+    }
+    while(!main_done)
+    {
+        char line[128];
+
+        /* command prompt */
+        printf( ">" );
+        fflush(stdout);
+
+        fgets (line, 128, stdin);
+
+        if (line[0]!= '\0')
+        {
+            /* remove linefeed */
+            line[strlen(line)-1] = 0;
+
+            process_cmd(line, 0);
+            memset(line, '\0', 128);
+        }
+    }
+
+    /* FIXME: Commenting this out as for some reason, the application does not exit otherwise*/
+    //bdt_cleanup();
+cleanup:
+    HAL_unload();
+
+    pthread_mutex_destroy(&deviceCount_mutex);
+    pthread_cond_destroy(&deviceCount_cond);
+
+    bdt_log(":: Bluedroid test app terminating");
+
+    return 0;
+}
diff --git a/test/l2test_ertm/Android.mk b/test/l2test_ertm/Android.mk
new file mode 100644
index 0000000..4355ab1
--- /dev/null
+++ b/test/l2test_ertm/Android.mk
@@ -0,0 +1,31 @@
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= l2test_ertm.c
+
+LOCAL_C_INCLUDES += . \
+    $(LOCAL_PATH)/../../stack/include \
+    $(LOCAL_PATH)/../../include \
+    $(LOCAL_PATH)/../../stack/l2cap \
+    $(LOCAL_PATH)/../../utils/include \
+    $(LOCAL_PATH)/../../ \
+    $(LOCAL_PATH)/btif/include \
+    $(bluetooth_C_INCLUDES)
+
+LOCAL_CFLAGS += $(bluetooth_CFLAGS)
+LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS)
+LOCAL_CPPFLAGS += $(bluetooth_CPPFLAGS)
+LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
+LOCAL_MODULE_TAGS := debug optional
+LOCAL_MODULE:= l2test_ertm
+
+LOCAL_SHARED_LIBRARIES += libcutils   \
+                          libutils    \
+                          libhardware \
+                          libhardware_legacy
+
+LOCAL_MULTILIB := 32
+
+include $(BUILD_EXECUTABLE)
diff --git a/test/l2test_ertm/l2test_ertm.c b/test/l2test_ertm/l2test_ertm.c
new file mode 100644
index 0000000..123042d
--- /dev/null
+++ b/test/l2test_ertm/l2test_ertm.c
@@ -0,0 +1,1310 @@
+/******************************************************************************
+ ** Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution.
+ *
+ *  Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/************************************************************************************
+ *
+ *  Filename:      l2test_ertm.c
+ *
+ *  Description:   Bluedroid L2CAP TOOL application
+ *
+ ***********************************************************************************/
+
+#include "l2c_api.h"
+#include <bt_testapp.h>
+
+#include <stdio.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/prctl.h>
+#include <sys/capability.h>
+#include <signal.h>
+#include <time.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include "bt_target.h"
+#include <private/android_filesystem_config.h>
+#include <android/log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/bluetooth.h>
+
+
+/************************************************************************************
+**  Constants & Macros
+************************************************************************************/
+
+#define PID_FILE "/data/.bdt_pid"
+
+#ifndef MAX
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+#endif
+
+#define TRANSPORT_BREDR 1  //Add tranport parameter to create bond
+
+/************************************************************************************
+**  Local type definitions
+************************************************************************************/
+
+enum {
+    DISCONNECT,
+    CONNECTING,
+    CONNECTED,
+    DISCONNECTING
+};
+
+static int g_ConnectionState = DISCONNECT;
+static int g_AdapterState = BT_STATE_OFF;
+static int g_PairState = BT_BOND_STATE_NONE;
+static UINT16 g_SecLevel = 0;
+static BOOLEAN g_SecOnlyMode = FALSE;
+static int g_secvalue = 0;
+static BOOLEAN g_ConnType = TRUE;//DUT is initiating connection
+static BOOLEAN g_Fcr_Present = FALSE;
+static bool g_Sar_Present = FALSE;
+static bool strict_mode = FALSE;
+static UINT8 g_Fcr_Mode = L2CAP_FCR_BASIC_MODE;
+static UINT8 g_Ertm_AllowedMode = (L2CAP_FCR_CHAN_OPT_BASIC | L2CAP_FCR_CHAN_OPT_ERTM | L2CAP_FCR_CHAN_OPT_STREAM);
+static int g_LocalBusy = 0;
+
+enum {
+    BT_TURNON_CMD,
+    BT_TURNOFF_CMD,
+    I_CONNECT_CMD,
+    O_CONNECT_CMD,
+    DISCONNECT_CMD,
+    SEND_DATA_CMD,
+    O_PAIR_CMD
+};
+
+enum {
+    SEND,
+    RECEIVE,
+    WAITANDSEND,
+    PAIR,
+    PING,
+    CONNECT,
+};
+
+static unsigned char *buf;
+/* Default mtu */
+static int g_imtu = 672;
+static int g_omtu = 0;
+
+
+/* Default data size */
+static long data_size = -1;
+static long buffer_size = 2048;
+
+static int master = 0;
+static int auth = 0;
+static int encrypt = 0;
+static int secure_m4_l4 = 0;
+/* Default number of frames */
+static int num_frames = 1;
+static int count = 1;
+
+/* Default delay before data transfer */
+static unsigned long g_delay = 1;
+
+static char *filename = NULL;
+
+
+/* Control channel eL2CAP default options */
+tL2CAP_FCR_OPTS ertm_fcr_opts_def = {
+    L2CAP_FCR_ERTM_MODE,
+    3, /* Tx window size */
+    MCA_FCR_OPT_MAX_TX_B4_DISCNT, /* Maximum transmissions before disconnecting */
+    2000, /* Retransmission timeout (2 secs) */
+    MCA_FCR_OPT_MONITOR_TOUT, /* Monitor timeout (12 secs) */
+    100 /* MPS segment size */
+};
+
+tL2CAP_FCR_OPTS stream_fcr_opts_def = {
+    L2CAP_FCR_STREAM_MODE,
+    3,/* Tx window size */
+    MCA_FCR_OPT_MAX_TX_B4_DISCNT, /* Maximum transmissions before disconnecting */
+    2000, /* Retransmission timeout (2 secs) */
+    MCA_FCR_OPT_MONITOR_TOUT, /* Monitor timeout (12 secs) */
+    100 /* MPS segment size */
+};
+static tL2CAP_ERTM_INFO t_ertm_info = {0,0,0,0,0,0};
+
+UINT8 do_l2cap_DataWrite(char *p , UINT32 len);
+
+
+/************************************************************************************
+**  Static variables
+************************************************************************************/
+
+static unsigned char main_done = 0;
+static bt_status_t status;
+
+/* Main API */
+static bluetooth_device_t* bt_device;
+
+const bt_interface_t* sBtInterface = NULL;
+
+static gid_t groups[] = { AID_NET_BT, AID_INET, AID_NET_BT_ADMIN,
+                          AID_SYSTEM, AID_MISC, AID_SDCARD_RW,
+                          AID_NET_ADMIN, AID_VPN};
+
+
+const btl2cap_interface_t *sL2capInterface = NULL;
+
+enum {
+L2CAP_NOT_CONNECTED,
+L2CAP_CONN_SETUP,
+L2CAP_CONNECTED
+};
+
+static int L2cap_conn_state = L2CAP_NOT_CONNECTED;
+static tL2CAP_CFG_INFO tl2cap_cfg_info;
+static UINT16           g_PSM           = 0;
+static UINT16           g_lcid          = 0;
+
+
+/************************************************************************************
+**  Static functions
+************************************************************************************/
+
+static int Send_Data();
+static int WaitForCompletion(int Cmd, int Timeout);
+
+
+/************************************************************************************
+**  Externs
+************************************************************************************/
+
+/************************************************************************************
+**  Functions
+************************************************************************************/
+
+
+//--------------------l2test----------------------------------------------------
+btl2cap_interface_t* get_l2cap_interface(void);
+
+
+
+static void l2test_l2c_connect_ind_cb(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
+{
+
+    if((L2CAP_FCR_ERTM_MODE == g_Fcr_Mode) || (L2CAP_FCR_STREAM_MODE == g_Fcr_Mode)) {
+        sL2capInterface->ErtmConnectRsp(bd_addr, id, lcid, L2CAP_CONN_OK, L2CAP_CONN_OK, &t_ertm_info);
+    } else {
+        sL2capInterface->ConnectRsp(bd_addr, id, lcid, L2CAP_CONN_OK, L2CAP_CONN_OK);
+    }
+    {
+        tL2CAP_CFG_INFO cfg;
+        memcpy (&cfg ,&tl2cap_cfg_info,sizeof(tl2cap_cfg_info));
+        if ((!sL2capInterface->ConfigReq (lcid, &cfg)) && cfg.fcr_present
+              && cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
+            cfg.fcr.mode = L2CAP_FCR_BASIC_MODE;
+            cfg.fcr_present = FALSE;
+            sL2capInterface->ConfigReq (lcid, &cfg);
+        }
+    }
+    g_ConnectionState = CONNECT;
+    g_lcid = lcid;
+}
+
+static void l2test_l2c_connect_cfm_cb(UINT16 lcid, UINT16 result)
+{
+
+    if (result == L2CAP_CONN_OK) {
+        L2cap_conn_state = L2CAP_CONN_SETUP;
+        tL2CAP_CFG_INFO cfg;
+        memcpy (&cfg ,&tl2cap_cfg_info,sizeof(tl2cap_cfg_info));
+        sL2capInterface->ConfigReq (lcid, &cfg);
+        g_imtu = cfg.mtu;
+        g_ConnectionState = CONNECT;
+        g_lcid = lcid;
+    }
+}
+
+static void l2test_l2c_connect_pnd_cb(UINT16 lcid)
+{
+    g_ConnectionState = CONNECTING;
+}
+static void l2test_l2c_config_ind_cb(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
+{
+    p_cfg->result = L2CAP_CFG_OK;
+    p_cfg->fcr_present = FALSE;
+    if(p_cfg->mtu_present) g_omtu = p_cfg->mtu;
+    else g_omtu = L2CAP_DEFAULT_MTU;
+    sL2capInterface->ConfigRsp (lcid, p_cfg);
+    return;
+}
+
+static void l2test_l2c_config_cfm_cb(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
+{
+
+    /* For now, always accept configuration from the other side */
+    if (p_cfg->result == L2CAP_CFG_OK) {
+        printf("\nl2test_l2c_config_cfm_cb Success\n");
+    } else {
+
+     /* If peer has rejected FCR and suggested basic then try basic */
+    if (p_cfg->fcr_present) {
+        tL2CAP_CFG_INFO cfg;
+        memcpy (&cfg ,&tl2cap_cfg_info,sizeof(tl2cap_cfg_info));
+        cfg.fcr_present = FALSE;
+        sL2capInterface->ConfigReq (lcid, &cfg);
+        // Remain in configure state
+        return;
+    }
+    sL2capInterface->DisconnectReq(lcid);
+    }
+    if(0 == g_omtu) g_omtu = L2CAP_DEFAULT_MTU;
+}
+
+static void l2test_l2c_disconnect_ind_cb(UINT16 lcid, BOOLEAN ack_needed)
+{
+    if (ack_needed)
+    {
+        /* send L2CAP disconnect response */
+        sL2capInterface->DisconnectRsp(lcid);
+    }
+    g_ConnectionState = DISCONNECTING;
+    g_lcid = 0;
+}
+static void l2test_l2c_disconnect_cfm_cb(UINT16 lcid, UINT16 result)
+{
+    g_ConnectionState = DISCONNECT;
+    g_lcid = 0;
+}
+static void l2test_l2c_QoSViolationInd(BD_ADDR bd_addr)
+{
+    printf("l2test_l2c_QoSViolationInd\n");
+}
+static void l2test_l2c_data_ind_cb(UINT16 lcid, BT_HDR *p_buf)
+{
+     printf("l2test_l2c_data_ind_cb:: event=%u, len=%u, offset=%u, layer_specific=%u\n", p_buf->event, p_buf->len, p_buf->offset, p_buf->layer_specific);
+}
+static void l2test_l2c_congestion_ind_cb(UINT16 lcid, BOOLEAN is_congested)
+{
+    printf("l2test_l2c_congestion_ind_cb\n");
+}
+
+static void l2test_l2c_tx_complete_cb (UINT16 lcid, UINT16 NoOfSDU)
+{
+    printf("l2test_l2c_tx_complete_cb, cid=0x%x, SDUs=%u\n", lcid, NoOfSDU);
+}
+
+static void l2c_echo_rsp_cb(UINT16 p)
+{
+    printf("Ping Response = %s\n", (L2CAP_PING_RESULT_OK==p) ?"Ping Reply OK" :(L2CAP_PING_RESULT_NO_LINK==p) ?"Link Could Not be setup" :"Remote L2cap did not reply");
+}
+
+/* L2CAP callback function structure */
+static tL2CAP_APPL_INFO l2test_l2c_appl = {
+  //  sizeof(l2test_l2c_appl),
+    l2test_l2c_connect_ind_cb,
+    l2test_l2c_connect_cfm_cb,
+    l2test_l2c_connect_pnd_cb,
+    l2test_l2c_config_ind_cb,
+    l2test_l2c_config_cfm_cb,
+    l2test_l2c_disconnect_ind_cb,
+    l2test_l2c_disconnect_cfm_cb,
+    l2test_l2c_QoSViolationInd,
+    l2test_l2c_data_ind_cb,
+    l2test_l2c_congestion_ind_cb,
+    l2test_l2c_tx_complete_cb
+};
+
+
+/************************************************************************************
+**  Shutdown helper functions
+************************************************************************************/
+
+static void bdt_shutdown(void)
+{
+    printf("shutdown bdroid test app\n");
+    main_done = 1;
+}
+
+
+/*****************************************************************************
+** Android's init.rc does not yet support applying linux capabilities
+*****************************************************************************/
+
+static void config_permissions(void)
+{
+    struct __user_cap_header_struct header;
+    struct __user_cap_data_struct cap[2];
+
+    printf("set_aid_and_cap : pid %d, uid %d gid %d", getpid(), getuid(), getgid());
+
+    header.pid = 0;
+
+    prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+
+    setuid(AID_BLUETOOTH);
+    setgid(AID_BLUETOOTH);
+    header.version = _LINUX_CAPABILITY_VERSION_3;
+
+    cap[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW);
+    cap[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN);
+    cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].permitted |= CAP_TO_MASK(CAP_NET_BIND_SERVICE);
+    cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].permitted |= CAP_TO_MASK(CAP_SYS_RAWIO);
+    cap[CAP_TO_INDEX(CAP_SYS_NICE)].permitted |= CAP_TO_MASK(CAP_SYS_NICE);
+    cap[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
+    cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].permitted |= CAP_TO_MASK(CAP_WAKE_ALARM);
+
+    cap[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW);
+    cap[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN);
+    cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].effective |= CAP_TO_MASK(CAP_NET_BIND_SERVICE);
+    cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].effective |= CAP_TO_MASK(CAP_SYS_RAWIO);
+    cap[CAP_TO_INDEX(CAP_SYS_NICE)].effective |= CAP_TO_MASK(CAP_SYS_NICE);
+    cap[CAP_TO_INDEX(CAP_SETGID)].effective |= CAP_TO_MASK(CAP_SETGID);
+    cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].effective |= CAP_TO_MASK(CAP_WAKE_ALARM);
+
+    capset(&header, &cap[0]);
+    setgroups(sizeof(groups)/sizeof(groups[0]), groups);
+}
+
+
+
+/*****************************************************************************
+**   Logger API
+*****************************************************************************/
+
+
+/*******************************************************************************
+ ** Console helper functions
+ *******************************************************************************/
+
+void skip_blanks(char **p)
+{
+  while (**p == ' ')
+    (*p)++;
+}
+
+#define is_cmd(str) ((strlen(str) == strlen(cmd)) && strncmp((const char *)&cmd, str, strlen(str)) == 0)
+#define if_cmd(str)  if (is_cmd(str))
+
+typedef void (t_console_cmd_handler) (char *p);
+
+typedef struct {
+    const char *name;
+    t_console_cmd_handler *handler;
+    const char *help;
+    unsigned char is_job;
+} t_cmd;
+
+
+#if 0
+static void cmdjob_handler(void *param)
+{
+    char *job_cmd = (char*)param;
+
+   // process_cmd(job_cmd, 1);
+    free(job_cmd);
+}
+
+static int create_cmdjob(char *cmd)
+{
+    pthread_t thread_id;
+    char *job_cmd;
+
+    job_cmd = malloc(strlen(cmd)+1); /* freed in job handler */
+    if (job_cmd) {
+        strlcpy(job_cmd, cmd, sizeof(job_cmd));
+
+        if (pthread_create(&thread_id, NULL,
+                       (void*)cmdjob_handler, (void*)job_cmd)!=0)
+            perror("pthread_create");
+    }
+
+    return 0;
+}
+#endif
+
+/*******************************************************************************
+ ** Load stack lib
+ *******************************************************************************/
+
+int HAL_load(void)
+{
+    int err = 0;
+
+    hw_module_t* module;
+    hw_device_t* device;
+
+    err = hw_get_module(BT_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
+    if (err == 0)
+    {
+        err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
+        if (err == 0) {
+            bt_device = (bluetooth_device_t *)device;
+            sBtInterface = bt_device->get_bluetooth_interface();
+        }
+    }
+
+    return err;
+}
+
+int HAL_unload(void)
+{
+    int err = 0;
+
+    sBtInterface = NULL;
+
+    return err;
+}
+
+/*******************************************************************************
+ ** HAL test functions & callbacks
+ *******************************************************************************/
+#if 0
+void setup_test_env(void)
+{
+    int i = 0;
+
+    while (console_cmd_list[i].name != NULL)
+    {
+        console_cmd_maxlen = MAX(console_cmd_maxlen, (int)strlen(console_cmd_list[i].name));
+        i++;
+    }
+}
+#endif
+
+void check_return_status(bt_status_t status)
+{
+    if (status != BT_STATUS_SUCCESS)
+    {
+         printf("HAL REQUEST FAILED\n");
+    }
+    else
+    {
+        printf("\nHAL REQUEST SUCCESS");
+    }
+}
+
+static void adapter_state_changed(bt_state_t state)
+{
+
+    int V1 = 1000, V2=2;
+    bt_property_t property = {9 /*BT_PROPERTY_DISCOVERY_TIMEOUT*/, 4, &V1};
+    bt_property_t property1 = {7 /*SCAN*/, 2, &V2};
+    bt_property_t property2 ={1,6,"Amith"};
+    g_AdapterState = state;
+
+    if (state == BT_STATE_ON) {
+        status = sBtInterface->set_adapter_property(&property1);
+        status = sBtInterface->set_adapter_property(&property);
+        status = sBtInterface->set_adapter_property(&property2);
+    }
+}
+
+static void adapter_properties_changed(bt_status_t status, int num_properties, bt_property_t *properties)
+{
+
+    char Bd_addr[15] = {0};
+    if(NULL == properties) {
+        return;
+    }
+    switch(properties->type)
+        {
+            case BT_PROPERTY_BDADDR:
+                memcpy(Bd_addr, properties->val, properties->len);
+            break;
+            default:
+            break;
+        }
+    return;
+}
+
+static void discovery_state_changed(bt_discovery_state_t state)
+{
+    printf("Discovery State Updated : %s\n", (state == BT_DISCOVERY_STOPPED)?"STOPPED":"STARTED");
+}
+
+#if 0
+static void pin_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name, uint32_t cod)
+{
+
+    int ret = 0;
+    bt_pin_code_t pincode = {{ 0x31, 0x32, 0x33, 0x34}};
+
+    if(BT_STATUS_SUCCESS != sBtInterface->pin_reply(remote_bd_addr, TRUE, 4, &pincode)) {
+        printf("Pin Reply failed\n");
+    }
+}
+#endif
+static void ssp_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name,
+                           uint32_t cod, bt_ssp_variant_t pairing_variant, uint32_t pass_key)
+{
+    if(BT_STATUS_SUCCESS != sBtInterface->ssp_reply(remote_bd_addr, pairing_variant, TRUE, pass_key)) {
+        printf("SSP Reply failed\n");
+    }
+}
+
+static void bond_state_changed_cb(bt_status_t status, bt_bdaddr_t *remote_bd_addr, bt_bond_state_t state)
+{
+
+    g_PairState = state;
+}
+
+static void acl_state_changed(bt_status_t status, bt_bdaddr_t *remote_bd_addr, bt_acl_state_t state)
+{
+}
+
+
+static void dut_mode_recv(uint16_t opcode, uint8_t *buf, uint8_t len)
+{
+    printf("DUT MODE RECEIVE : NOT IMPLEMENTED\n");
+}
+
+static bt_callbacks_t bt_callbacks = {
+    sizeof(bt_callbacks_t),
+    adapter_state_changed,
+    adapter_properties_changed, /*adapter_properties_cb */
+    NULL, /* remote_device_properties_cb */
+    NULL, /* device_found_cb */
+    discovery_state_changed, /* discovery_state_changed_cb */
+    NULL, /* pin_request_cb  */
+    ssp_request_cb, /* ssp_request_cb  */
+    bond_state_changed_cb, /*bond_state_changed_cb */
+    acl_state_changed, /* acl_state_changed_cb */
+    NULL, /* thread_evt_cb */
+    dut_mode_recv, /*dut_mode_recv_cb */
+    NULL, /*le_test_mode_cb*/
+    NULL, /*energy_info_cb */
+    NULL, /*get_testapp_interface */
+};
+
+static bool set_wake_alarm(uint64_t delay_millis, bool should_wake, alarm_cb cb, void *data) {
+  static timer_t timer;
+  static bool timer_created;
+
+  if (!timer_created) {
+    struct sigevent sigevent;
+    memset(&sigevent, 0, sizeof(sigevent));
+    sigevent.sigev_notify = SIGEV_THREAD;
+    sigevent.sigev_notify_function = (void (*)(union sigval))cb;
+    sigevent.sigev_value.sival_ptr = data;
+    timer_create(CLOCK_MONOTONIC, &sigevent, &timer);
+    timer_created = true;
+  }
+
+  struct itimerspec new_value;
+  new_value.it_value.tv_sec = delay_millis / 1000;
+  new_value.it_value.tv_nsec = (delay_millis % 1000) * 1000 * 1000;
+  new_value.it_interval.tv_sec = 0;
+  new_value.it_interval.tv_nsec = 0;
+  timer_settime(timer, 0, &new_value, NULL);
+
+  return true;
+}
+
+static int acquire_wake_lock(const char *lock_name) {
+  return BT_STATUS_SUCCESS;
+}
+
+static int release_wake_lock(const char *lock_name) {
+  return BT_STATUS_SUCCESS;
+}
+
+static bt_os_callouts_t callouts = {
+    sizeof(bt_os_callouts_t),
+    set_wake_alarm,
+    acquire_wake_lock,
+    release_wake_lock,
+};
+
+
+void bdt_init(void)
+{
+    printf("INIT BT \n");
+    status = sBtInterface->init(&bt_callbacks);
+    if (status == BT_STATUS_SUCCESS) {
+        status = sBtInterface->set_os_callouts(&callouts);
+    }
+    check_return_status(status);
+}
+
+void bdt_enable(void)
+{
+    //int status = 0;
+    printf("ENABLE BT\n");
+    if (BT_STATE_ON == g_AdapterState) {
+        printf("Bluetooth is already enabled\n");
+        return;
+    }
+    status = sBtInterface->enable(strict_mode);
+    return;
+}
+
+void  bdt_disable(void)
+{
+    if (BT_STATE_ON != g_AdapterState)
+    {
+        return;
+    }
+    status = sBtInterface->disable();
+    check_return_status(status);
+    return;
+}
+
+void bdt_cleanup(void)
+{
+    sBtInterface->cleanup();
+}
+
+btl2cap_interface_t* get_l2cap_interface(void)
+{
+    if ((sBtInterface)&&(sBtInterface->get_testapp_interface)) {
+        return (btl2cap_interface_t *) sBtInterface->get_testapp_interface(TEST_APP_L2CAP);
+    }
+    return NULL;
+}
+
+/*******************************************************************************
+ ** Console commands
+ *******************************************************************************/
+
+void do_quit(char *p)
+{
+    bdt_shutdown();
+}
+
+/*******************************************************************
+ *
+ *  BT TEST  CONSOLE COMMANDS
+ *
+ *  Parses argument lists and passes to API test function
+ *
+*/
+
+void do_init(char *p)
+{
+    bdt_init();
+}
+
+BOOLEAN do_enable(char *p)
+{
+    bdt_enable();
+    if(0 != WaitForCompletion(BT_TURNON_CMD, 10))
+    {
+        printf("BT Turn ON Failed... Exiting...\n");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+BOOLEAN do_disable(char *p)
+{
+    bdt_disable();
+    if(0 != WaitForCompletion(BT_TURNOFF_CMD, 10))
+    {
+        printf("BT Turn OFF Failed... Exiting...\n");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+void do_cleanup(char *p)
+{
+   // bdt_cleanup();
+}
+
+int GetBdAddr(char *p, bt_bdaddr_t *pbd_addr)
+{
+    char Arr[13] = {0};
+    UINT8 k1 = 0;
+    UINT8 k2 = 0;
+    int i;
+
+    if(12 != strlen(p))
+    {
+        printf("\nInvalid Bd Address. Format[112233445566]\n");
+        return FALSE;
+    }
+    strlcpy(Arr, p, sizeof(Arr));
+    for(i=0; i<12; i++)
+    {
+        Arr[i] = tolower(Arr[i]);
+    }
+    for(i=0; i<6; i++)
+    {
+        k1 = (UINT8) ( (Arr[i*2] >= 'a') ? ( 10 + (UINT8)( Arr[i*2] - 'a' )) : (Arr[i*2] - '0') );
+        k2 = (UINT8) ( (Arr[i*2+1] >= 'a') ? ( 10 + (UINT8)( Arr[i*2+1] - 'a' )) : (Arr[i*2+1] - '0') );
+        if ( (k1>15)||(k2>15) )
+        {
+            return FALSE;
+        }
+        pbd_addr->address[i] = (k1<<4 | k2);
+    }
+    return TRUE;
+}
+
+void do_l2cap_init(char *p)
+{
+
+
+    memset(&tl2cap_cfg_info, 0, sizeof(tl2cap_cfg_info));
+    //Use macros for the constants
+    tl2cap_cfg_info.mtu_present = TRUE;
+    tl2cap_cfg_info.mtu = g_imtu;
+    tl2cap_cfg_info.flush_to_present = TRUE;
+    tl2cap_cfg_info.flush_to = 0xffff;
+    //use other param if needed
+    tl2cap_cfg_info.fcr_present = g_Fcr_Present;
+    tl2cap_cfg_info.fcr.mode = g_Fcr_Mode;
+    tl2cap_cfg_info.fcs = 0;
+    tl2cap_cfg_info.fcs_present = 1;
+
+    tl2cap_cfg_info.fcr.tx_win_sz = 3;
+    if(L2CAP_FCR_ERTM_MODE == tl2cap_cfg_info.fcr.mode)
+    {
+        tl2cap_cfg_info.fcr = ertm_fcr_opts_def;
+    }
+    else if(L2CAP_FCR_STREAM_MODE == tl2cap_cfg_info.fcr.mode)
+    {
+        tl2cap_cfg_info.fcr = stream_fcr_opts_def;
+    }
+    //Initialize ERTM Parameters
+    t_ertm_info.preferred_mode = g_Fcr_Mode;
+    t_ertm_info.allowed_modes = g_Ertm_AllowedMode;
+    t_ertm_info.user_rx_buf_size  = BT_DEFAULT_BUFFER_SIZE;
+    t_ertm_info.user_tx_buf_size = BT_DEFAULT_BUFFER_SIZE;
+    t_ertm_info.fcr_rx_buf_size = BT_DEFAULT_BUFFER_SIZE;
+    t_ertm_info.fcr_tx_buf_size = BT_DEFAULT_BUFFER_SIZE;
+    //Load L2cap Interface
+    if(NULL == sL2capInterface)
+    {
+        sL2capInterface = get_l2cap_interface();
+    }
+    if (sL2capInterface)
+        sL2capInterface->Init(&l2test_l2c_appl);
+}
+
+void do_l2cap_deregister(char *p)
+{
+
+    sL2capInterface->Deregister(g_PSM);
+}
+
+UINT16 do_l2cap_connect(char *p)
+{
+
+    bt_bdaddr_t bd_addr = {{0}};
+    GetBdAddr(p, &bd_addr);
+
+    if((L2CAP_FCR_STREAM_MODE == g_Fcr_Mode) || (L2CAP_FCR_ERTM_MODE == g_Fcr_Mode)) {
+        return sL2capInterface->ErtmConnectReq(g_PSM,(uint8_t *)&bd_addr.address, &t_ertm_info);
+    } else {
+        return sL2capInterface->Connect(g_PSM, &bd_addr);
+    }
+}
+
+BOOLEAN do_l2cap_ping(char *p)
+{
+
+    bt_bdaddr_t bd_addr = {{0}};
+    GetBdAddr(p, &bd_addr);
+    if(FALSE == sL2capInterface->Ping(bd_addr.address, l2c_echo_rsp_cb)) {
+        printf("Failed to send Ping Request \n");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+
+BOOLEAN do_l2cap_disconnect(char *p)
+{
+    return sL2capInterface->DisconnectReq(g_lcid);
+}
+
+UINT8 do_l2cap_DataWrite(char *p , UINT32 len)
+{
+    return sL2capInterface->DataWrite(g_lcid, p, len);
+}
+
+void    do_l2cap_SetSecConnOnlyMode(BOOLEAN secvalue)
+{
+       sL2capInterface->SetSecConnOnlyMode(secvalue);
+}
+static int WaitForCompletion(int Cmd, int Timeout)
+{
+    int Status = 0xFF;
+    int *pState = NULL;
+    switch(Cmd)
+    {
+    case BT_TURNON_CMD:
+        Status = BT_STATE_ON;
+        pState = &g_AdapterState;
+        break;
+    case BT_TURNOFF_CMD:
+        Status = BT_STATE_OFF;
+        pState = &g_AdapterState;
+        break;
+    case I_CONNECT_CMD:
+        Status = CONNECT;
+        pState = &g_ConnectionState;
+        break;
+    case O_CONNECT_CMD:
+        Status = CONNECT;
+        pState = &g_ConnectionState;
+        break;
+    case DISCONNECT_CMD:
+        Status = DISCONNECT;
+        pState = &g_ConnectionState;
+        break;
+    case SEND_DATA_CMD:
+        //
+        break;
+    case O_PAIR_CMD:
+        Status = BT_BOND_STATE_BONDED;
+        pState = &g_PairState;
+        break;
+    }
+    if(NULL == pState)
+        return 0xFF;
+    while( (Status != *pState) && (Timeout--) )
+    {
+        sleep(1);
+    }
+    if(Status != *pState)
+        return 1;     //Timeout
+    else
+        return 0;     //Success
+}
+
+static void l2c_listen(int SendData)
+{
+    printf("Waiting for Incoming connection... \n");
+    if(0 != WaitForCompletion(I_CONNECT_CMD, 60))
+    {
+        printf("No incoming connection... Exiting...\n");
+        return;
+    }
+    if(TRUE == SendData)
+    {
+    printf(" going to send data...\n");
+    Send_Data();
+    }
+}
+
+static int Send_Data()
+{
+    int fd, size;
+    char *tmpBuf = NULL;
+
+    if (data_size < 0)
+        data_size = g_omtu;
+    printf("data_size = %ld, g_omtu=%d", data_size, g_omtu);
+
+    tmpBuf = malloc(data_size);
+    if(NULL == tmpBuf)
+    {
+        printf("Malloc failed \n");
+        return FALSE;
+    }
+    if (filename) {
+        fd = open(filename, O_RDONLY);
+        printf("Filename for input data = %s \n", filename);
+        if (fd < 0) {
+        printf("Open failed: %s (%d)\n", strerror(errno), errno);
+        exit(1);
+    }
+    while (1) {
+        size = read(fd, tmpBuf, data_size);
+        if(size <= 0) {
+            printf("\n File end ");
+            break;
+        }
+    do_l2cap_DataWrite(tmpBuf, size);
+    }
+    return TRUE;
+    } else {
+        memset(tmpBuf, '\x7f', data_size);
+    }
+    if (num_frames && g_delay && count) {
+    printf("Delay before first send ... %lu msec, size=%ld \n", g_delay/1000, data_size);
+    usleep(g_delay);
+    }
+    printf(" count %d...\n", count);
+    sleep(5);
+    while (count > 0) {
+        char tmpBuffer[] = {0x11,0x04,0x7F,0x7F,0x7F,0x7F,0x7F,
+                        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+                        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+                        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+                        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+                        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+                        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+                        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+                        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+                        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
+                        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F
+                      };
+        count--;
+        printf("Before write count is %d...\n", count);
+        if( g_Sar_Present == TRUE)
+        {
+        sleep(5);
+        printf("SAR present..\n");
+        do_l2cap_DataWrite(tmpBuffer, 100);
+        sleep(5);
+        do_l2cap_DataWrite(tmpBuffer, 100);
+        }
+        else
+        do_l2cap_DataWrite(tmpBuffer, 5);
+    }
+    sleep(50);
+    free(tmpBuf);
+    return TRUE;
+}
+
+static void l2c_connect(char *svr)
+{
+
+    printf("In l2c_connect - %s \n", svr);
+    do_l2cap_connect(svr);
+}
+
+static void l2c_send(char *p)
+{
+
+    do_l2cap_connect(p);
+    if(0 != WaitForCompletion(I_CONNECT_CMD, 10)) {
+        printf("Connection didnot happen in 10sec... Returning Failure...\n");
+        return;
+    }
+    sleep(1); //Let Config to complete
+    Send_Data();
+}
+
+static int l2c_pair(char *p)
+{
+    bt_bdaddr_t bd_addr = {{0}};
+    GetBdAddr(p, &bd_addr);
+    if(BT_STATUS_SUCCESS != sBtInterface->create_bond(&bd_addr,TRANSPORT_BREDR))
+    {
+        printf("Failed to Initiate Pairing \n");
+        return FALSE;
+    }
+    if(0 != WaitForCompletion(O_PAIR_CMD, 15))
+    {
+        printf("Pairing didnot happen in 15sec... Returning Failure...\n");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+static void l2c_ping(char *svr)
+{
+
+    printf("In l2c_ping - %s \n", svr);
+    do_l2cap_ping(svr);
+}
+
+static void l2c_disconnect(char *p)
+{
+    printf("In l2c_disconnect\n");
+    do_l2cap_disconnect(p);
+}
+
+static void options(void)
+{
+    printf("Modes:\n"
+                "\t-c connect\n"
+                "\t-r receive\n"
+                "\t-s connect and send\n"
+                "\t-w wait and send\n"
+                "\t-p bonding\n"
+                "\t-a ping\n");
+    printf("Options:\n"
+                "\t[-b bytes] [-i device] [-P psm] [-J cid]\n"
+                "\t[-I imtu] [-O omtu]\n"
+                "\t[-L localBusy status] 1-localbusy, 0-otherwise (default=0)\n"
+                "\t[-N num] send num frames (default = infinite)\n"
+                "\t[-C num] Count(default = 1)\n"
+                "\t[-D milliseconds] delay after sending num frames (default = 0)\n"
+                "\t[-X mode] select retransmission/flow-control mode\n"
+                    "\t(ertm, ertm-mandatory, streaming, streaming-mandatory)\n"
+                "\t[-Q num] retransmit each packet up to num times (default = 3)\n"
+                "\t[-A] authentication\n"
+                "\t[-E] encryption\n"
+                "\t[-S] secure connection\n"
+                "\t[-T] timestamps\n"
+                "\t[-H mode] 1-SecConnOnlyModeTrue 0-SecConnOnlyModeFalse\n");
+}
+
+static int len = 0;
+
+int main(int argc, char *argv[])
+{
+    struct sigaction sa;
+    int opt, mode = RECEIVE, addr_required = 0;
+    char temp[3] = {0};
+
+    while ((opt=getopt(argc,argv,"arswcpb:i:P:K:O:H:F:N:L:C:D:X:Q:I:W:Z:UGATMES")) != EOF) {
+        switch(opt) {
+            case 'a':
+                mode = PING;
+                addr_required = 1;
+                break;
+            case 'r':
+                mode = RECEIVE;
+                g_ConnType = FALSE;
+                break;
+
+            case 's':
+                mode = SEND;
+                g_ConnType = TRUE;
+                addr_required = 1;
+                break;
+
+            case 'w':
+                mode = WAITANDSEND;
+                g_ConnType = FALSE;
+                break;
+
+            case 'c':
+                mode = CONNECT;
+                g_ConnType = TRUE;
+                addr_required = 1;
+                break;
+
+            case 'p':
+                mode = PAIR;
+                addr_required = 1;
+                break;
+
+            case 'b':
+                data_size = atoi(optarg);
+                break;
+
+            case 'A':
+                auth = 1;
+                break;
+            case 'C':
+                count = atoi(optarg);
+                break;
+            case 'D':
+                g_delay = atoi(optarg) * 1000;
+                break;
+            case 'E':
+                encrypt = 1;
+                break;
+            case 'F':
+                filename = strdup(optarg);
+                break;
+            case 'H':
+                g_SecOnlyMode = TRUE;
+                g_secvalue = atoi(optarg);
+                break;
+            case 'I':
+                g_imtu = atoi(optarg);
+                break;
+
+            case 'L':
+                g_LocalBusy = atoi(optarg);
+                break;
+
+            case 'M':
+                master = 1;
+                break;
+
+            case 'N':
+                num_frames = atoi(optarg);
+                break;
+
+            case 'O':
+                g_omtu = atoi(optarg);
+                break;
+
+            case 'P':
+                g_PSM = atoi(optarg);
+                printf("PSM %d",g_PSM);
+                break;
+            case 'S':
+                secure_m4_l4 = 1;
+                break;
+
+            case 'Q':
+                ertm_fcr_opts_def.max_transmit = atoi(optarg);
+                stream_fcr_opts_def.max_transmit = ertm_fcr_opts_def.max_transmit;
+                break;
+
+            case 'X':
+                if (strcasecmp(optarg, "ertm-mandatory") == 0) {
+                    g_Fcr_Present = TRUE;
+                    g_Fcr_Mode = L2CAP_FCR_ERTM_MODE;
+                    g_Ertm_AllowedMode = L2CAP_FCR_CHAN_OPT_ERTM;
+                    printf("in ERTM Mandatory option - 1\n");
+                } else if (strcasecmp(optarg, "ertm") == 0) {
+                    g_Fcr_Present = TRUE;
+                    g_Fcr_Mode = L2CAP_FCR_ERTM_MODE;
+                    printf("in ERTM option \n");
+                } else if (strcasecmp(optarg, "streaming-mandatory") == 0) {
+                    printf("FCR Mode selected as Streaming Mandatory\n");
+                    g_Fcr_Present = TRUE;
+                    g_Fcr_Mode = L2CAP_FCR_STREAM_MODE;
+                    g_Ertm_AllowedMode = L2CAP_FCR_CHAN_OPT_STREAM;
+                } else if (strcasecmp(optarg, "streaming") == 0) {
+                    g_Fcr_Present = TRUE;
+                    printf("FCR Mode selected as Streaming\n");
+                    g_Fcr_Mode = L2CAP_FCR_STREAM_MODE;
+                } else {
+                    g_Fcr_Mode = L2CAP_FCR_BASIC_MODE;
+                    printf("FCR Mode selected as Basic. String passed matches none\n");
+                }
+                break;
+
+            case 'W':
+                ertm_fcr_opts_def.tx_win_sz = atoi(optarg);
+                stream_fcr_opts_def.tx_win_sz = ertm_fcr_opts_def.tx_win_sz;
+                tl2cap_cfg_info.fcr.tx_win_sz = ertm_fcr_opts_def.tx_win_sz;
+                break;
+            case 'Z':
+                 g_Sar_Present = TRUE;
+                 printf("g_Sar_Present = true \n");
+                 break;
+            default:
+            options();
+            exit(1);
+        }
+    }
+    if (addr_required && !(argc - optind)) {
+        options();
+        exit(1);
+    }
+
+    if (data_size < 0)
+        buffer_size = (g_omtu > g_imtu) ? g_omtu : g_imtu;
+    else
+        buffer_size = data_size;
+
+    if (!(buf = malloc(buffer_size))) {
+        perror("Can't allocate data buffer");
+        exit(1);
+    }
+
+    memset(&sa, 0, sizeof(sa));
+    sa.sa_handler = SIG_IGN;
+    sa.sa_flags   = SA_NOCLDSTOP;
+    sigaction(SIGCHLD, &sa, NULL);
+
+    config_permissions();
+    if ( HAL_load() < 0 ) {
+        perror("HAL failed to initialize, exit\n");
+        unlink(PID_FILE);
+        exit(0);
+    }
+
+    //setup_test_env();
+    bdt_init();
+    sleep(5);
+    if(FALSE == do_enable(NULL))
+        goto ERR;
+        printf("\n Before l2cap init\n");
+        do_l2cap_init(NULL);
+        printf("\n after l2cap init\n");
+        if (g_SecOnlyMode)
+        {
+        printf("\n Before Setting SecureConnectionsOnlyMode");
+          do_l2cap_SetSecConnOnlyMode(TRUE);
+        printf("\n After Setting SecureConnectionsOnlyMode");
+        }
+    //Outgoing Connection
+    if(TRUE == g_ConnType)
+    {
+        if(1 == auth)    g_SecLevel |= BTM_SEC_OUT_AUTHENTICATE;
+        if(1 == encrypt) g_SecLevel |= BTM_SEC_OUT_ENCRYPT ;
+        if(1 == secure_m4_l4) g_SecLevel |= BTM_SEC_MODE4_LEVEL4;
+    } else {
+        if(1 == auth)    g_SecLevel |= BTM_SEC_IN_AUTHENTICATE;
+        if(1 == encrypt) g_SecLevel |= BTM_SEC_IN_ENCRYPT ;
+        if(1 == secure_m4_l4) g_SecLevel |= BTM_SEC_MODE4_LEVEL4;
+    }
+
+    if(0 != g_PSM)
+        {
+            printf("g_SecLevel = %d \n", g_SecLevel);
+            sL2capInterface->RegisterPsm(g_PSM, g_ConnType, g_SecLevel /*BTM_SEC_IN_AUTHORIZE */);
+            sleep(3);
+        }
+
+    switch (mode) {
+        case RECEIVE:
+            l2c_listen(FALSE);
+            break;
+
+        case SEND:
+            l2c_send(argv[optind]);
+            break;
+
+        case WAITANDSEND:
+            l2c_listen(TRUE);
+            break;
+
+        case CONNECT:
+            l2c_connect(argv[optind]);
+            break;
+
+        case PING:
+            l2c_ping(argv[optind]);
+            break;
+
+        case PAIR:
+            l2c_pair(argv[optind]);
+            if(0 != g_PSM) {
+                sleep(2);
+                l2c_connect(argv[optind]);
+            }
+            break;
+       }
+
+    if(0 != g_LocalBusy) {
+        sleep(5);
+        printf("To Send Local BusyStatus.... Press any key\n");
+        read(0, &temp, 2);
+        sL2capInterface->FlowControl(g_lcid, 0); //second param is 'dataEnabled', making it false means localBusy
+    }
+
+ERR:
+    while(1) {
+        sleep(5);
+        printf("Enter Y/y to Exit... \n");
+        len = read(0, &temp, 2);
+        if((temp[0] == 'Y') || (temp[0] == 'y'))
+        break;
+    }
+    //bdt_cleanup();
+    if(g_ConnectionState == CONNECT) {
+        l2c_disconnect(NULL);
+        sleep(5);
+    }
+    do_disable(NULL);
+    HAL_unload();
+    return 0;
+}
diff --git a/test/mcap_tool/Android.mk b/test/mcap_tool/Android.mk
new file mode 100644
index 0000000..47785b4
--- /dev/null
+++ b/test/mcap_tool/Android.mk
@@ -0,0 +1,36 @@
+#
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+
+LOCAL_SRC_FILES:= mcap_tool.c
+
+LOCAL_C_INCLUDES += . \
+        $(LOCAL_PATH)/../../stack/include \
+        $(LOCAL_PATH)/../../include \
+        $(LOCAL_PATH)/../../stack/l2cap \
+        $(LOCAL_PATH)/../../utils/include \
+        $(LOCAL_PATH)/../../ \
+        $(LOCAL_PATH)/btif/include \
+        $(bluetooth_C_INCLUDES)
+
+LOCAL_CFLAGS += $(bluetooth_CFLAGS)
+LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
+LOCAL_MODULE_TAGS := debug optional
+
+LOCAL_MODULE:= mcap_tool
+
+
+LOCAL_SHARED_LIBRARIES += libcutils   \
+                          libutils    \
+                          libhardware \
+                          libhardware_legacy
+
+
+LOCAL_MULTILIB := 32
+
+
+include $(BUILD_EXECUTABLE)
diff --git a/test/mcap_tool/mcap_tool.c b/test/mcap_tool/mcap_tool.c
new file mode 100644
index 0000000..861aaf6
--- /dev/null
+++ b/test/mcap_tool/mcap_tool.c
@@ -0,0 +1,1178 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2015, The linux Foundation. All rights reserved.
+ *
+ *  Not a Contribution.
+ *
+ *  Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/************************************************************************************
+ *
+ *  Filename:      mcap_tool.c
+ *
+ *  Description:   Bluedroid MCAP TOOL application
+ *
+ ***********************************************************************************/
+
+#include <stdio.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/prctl.h>
+#include <sys/capability.h>
+#include "l2c_api.h"
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <private/android_filesystem_config.h>
+#include <android/log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/bluetooth.h>
+#include "bt_testapp.h"
+#include  "mca_defs.h"
+#include "mca_api.h"
+
+
+/************************************************************************************
+**  Constants & Macros
+************************************************************************************/
+//#define		TRUE		1
+//#define		FALSE		0
+
+#define PID_FILE "/data/.bdt_pid"
+
+#ifndef MAX
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+#endif
+
+#define CASE_RETURN_STR(const) case const: return #const;
+#define TRANSPORT_BREDR 1  //Add tranport parameter to create bond
+
+/************************************************************************************
+**  Local type definitions
+************************************************************************************/
+
+/************************************************************************************
+**  Static variables
+************************************************************************************/
+
+static unsigned char main_done = 0;
+static bt_status_t status;
+static bool strict_mode = FALSE;
+
+/* Main API */
+static bluetooth_device_t* bt_device;
+
+const bt_interface_t* sBtInterface = NULL;
+
+static gid_t groups[] = { AID_NET_BT, AID_INET, AID_NET_BT_ADMIN,
+                          AID_SYSTEM, AID_MISC, AID_SDCARD_RW,
+                          AID_NET_ADMIN, AID_VPN};
+
+/* Set to 1 when the Bluedroid stack is enabled */
+static unsigned char bt_enabled = 0;
+
+
+
+
+enum {
+    DISCONNECT,
+    CONNECTING,
+    CONNECTED,
+    DISCONNECTING
+};
+static int      g_AdapterState     = BT_STATE_OFF;
+static int      g_PairState     = BT_BOND_STATE_NONE;
+
+btmcap_interface_t   *sMcapIface  = NULL;
+tMCA_HANDLE    g_Mcap_Handle = 0;
+tMCA_DEP       g_Mcap_Dep    = 0;
+tL2CAP_FCR_OPTS    g_fcr_opts   = {
+    L2CAP_FCR_ERTM_MODE,
+    MCA_FCR_OPT_TX_WINDOW_SIZE,   /* Tx window size */
+    MCA_FCR_OPT_MAX_TX_B4_DISCNT, /* Maximum transmissions before disconnecting */
+    MCA_FCR_OPT_RETX_TOUT,        /* Retransmission timeout (2 secs) */
+    MCA_FCR_OPT_MONITOR_TOUT,     /* Monitor timeout (12 secs) */
+    MCA_FCR_OPT_MPS_SIZE          /* MPS segment size */
+};
+
+tMCA_CHNL_CFG g_chnl_cfg = {
+    {
+        L2CAP_FCR_ERTM_MODE,
+        MCA_FCR_OPT_TX_WINDOW_SIZE,   /* Tx window size */
+        MCA_FCR_OPT_MAX_TX_B4_DISCNT, /* Maximum transmissions before disconnecting */
+        MCA_FCR_OPT_RETX_TOUT,        /* Retransmission timeout (2 secs) */
+        MCA_FCR_OPT_MONITOR_TOUT,     /* Monitor timeout (12 secs) */
+        MCA_FCR_OPT_MPS_SIZE          /* MPS segment size */
+    },
+    BT_DEFAULT_BUFFER_SIZE,
+    BT_DEFAULT_BUFFER_SIZE,
+    BT_DEFAULT_BUFFER_SIZE,
+    BT_DEFAULT_BUFFER_SIZE,
+    MCA_FCS_NONE,
+    572
+};
+
+UINT16   g_Peer_Mtu  = 0;
+UINT16   g_Mdl_Id    = 0;
+tMCA_DL  g_Mdl       = 0;
+tMCA_CL  g_Mcl  = 0;
+
+
+/************************************************************************************
+**  Static functions
+************************************************************************************/
+
+static void process_cmd(char *p, unsigned char is_job);
+static void bdt_log(const char *fmt_str, ...);
+
+int GetBdAddr(char *p, bt_bdaddr_t *pbd_addr);
+
+static int str2bd(char *str, bt_bdaddr_t *addr)
+{
+    int32_t i = 0;
+
+    for (i = 0; i < 6; i++)
+    {
+        addr->address[i] = (uint8_t) strtoul(str, (char **)&str, 16);
+        str++;
+    }
+    return 0;
+}
+
+/************************************************************************************
+**  Externs
+************************************************************************************/
+
+/************************************************************************************
+**  MCAP Callbacks
+************************************************************************************/
+static void mcap_ctrl_cb(tMCA_HANDLE handle, tMCA_CL mcl, UINT8 event, tMCA_CTRL *p_data)
+{
+    tMCA_RESULT Ret;
+    //printf("%s:: handle=%d, mcl=%d, event=0x%x, g_Mdl=%d, g_Mdl_Id=%d \n", __FUNCTION__, handle, mcl, event, g_Mdl, g_Mdl_Id);
+    switch(event)
+    {
+        case MCA_CREATE_IND_EVT:
+           //printf("%s::Create_ind::Mdl_Id=%d, OpCode=%d, dep_id=%d, cfg=%d \n", __FUNCTION__, p_data->create_ind.mdl_id,
+           //p_data->create_ind.op_code, p_data->create_ind.dep_id, p_data->create_ind.cfg);
+           g_Mdl = p_data->create_ind.mdl_id;
+           Ret = sMcapIface->CreateMdlRsp(mcl, p_data->create_ind.dep_id,
+                                  g_Mdl, p_data->create_ind.cfg, MCA_SUCCESS, &g_chnl_cfg);
+        break;
+
+        case MCA_CONNECT_IND_EVT:
+            //printf("%s::Connect_Ind:: peer_mtu=%d \n", __FUNCTION__, p_data->connect_ind.mtu);
+            g_Mcl = mcl;
+        break;
+
+        case MCA_DISCONNECT_IND_EVT:
+            g_Mcl = 0;
+        break;
+
+        case MCA_OPEN_IND_EVT:
+        case MCA_OPEN_CFM_EVT:
+           g_Mdl_Id = p_data->open_ind.mdl_id;
+           g_Mdl    = p_data->open_ind.mdl;
+           g_Peer_Mtu  = p_data->open_ind.mtu;
+        break;
+
+        case MCA_RECONNECT_IND_EVT:
+            //printf("%s::Reconnect Ind:: Mdl_Id=%d, g_Mdl_Id=%d\n", __FUNCTION__, p_data->reconnect_ind.mdl_id, g_Mdl_Id);
+            Ret = sMcapIface->ReconnectMdlRsp(mcl, g_Mcap_Dep, p_data->reconnect_ind.mdl_id, (g_Mdl_Id==p_data->reconnect_ind.mdl_id) ?MCA_RSP_SUCCESS :MCA_RSP_BAD_MDL, &g_chnl_cfg);
+        break;
+
+       case MCA_DELETE_IND_EVT:
+           //printf("%s::Delete Ind:: Mdl_Id=%d\n", __FUNCTION__, p_data->delete_ind.mdl_id);
+           if((0xffff==p_data->delete_ind.mdl_id)||(g_Mdl_Id == p_data->delete_ind.mdl_id))	g_Mdl_Id = 0;
+       break;
+
+       case MCA_SYNC_CAP_IND_EVT:
+           //printf("%s::Sync Cap Ind::\n", __FUNCTION__);
+       break;
+
+       case MCA_ABORT_IND_EVT:
+           //printf("%s::Abort_Ind::Mdl_Id=%d, opCode=%d \n", __FUNCTION__, p_data->abort_ind.mdl_id, p_data->abort_ind.op_code);
+       break;
+    }
+}
+
+static void mcap_data_cb(tMCA_DL mdl, BT_HDR *p_pkt)
+{
+    //printf("%s:: mdl=%d, event=%d, len=%d, offset=%d, layer_specific=%d\n", __FUNCTION__, mdl, p_pkt->event, p_pkt->len, p_pkt->offset, p_pkt->layer_specific);
+}
+
+
+
+/************************************************************************************
+**  Shutdown helper functions
+************************************************************************************/
+
+static void bdt_shutdown(void)
+{
+    bdt_log("shutdown bdroid test app\n");
+    main_done = 1;
+}
+
+
+/*****************************************************************************
+** Android's init.rc does not yet support applying linux capabilities
+*****************************************************************************/
+
+static void config_permissions(void)
+{
+    struct __user_cap_header_struct header;
+    struct __user_cap_data_struct cap[2];
+
+    bdt_log("set_aid_and_cap : pid %d, uid %d gid %d", getpid(), getuid(), getgid());
+
+    header.pid = 0;
+
+    prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+
+    setuid(AID_BLUETOOTH);
+    setgid(AID_BLUETOOTH);
+
+    header.version = _LINUX_CAPABILITY_VERSION_3;
+
+    cap[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW);
+    cap[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN);
+    cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].permitted |= CAP_TO_MASK(CAP_NET_BIND_SERVICE);
+    cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].permitted |= CAP_TO_MASK(CAP_SYS_RAWIO);
+    cap[CAP_TO_INDEX(CAP_SYS_NICE)].permitted |= CAP_TO_MASK(CAP_SYS_NICE);
+    cap[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
+    cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].permitted |= CAP_TO_MASK(CAP_WAKE_ALARM);
+
+    cap[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW);
+    cap[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN);
+    cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].effective |= CAP_TO_MASK(CAP_NET_BIND_SERVICE);
+    cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].effective |= CAP_TO_MASK(CAP_SYS_RAWIO);
+    cap[CAP_TO_INDEX(CAP_SYS_NICE)].effective |= CAP_TO_MASK(CAP_SYS_NICE);
+    cap[CAP_TO_INDEX(CAP_SETGID)].effective |= CAP_TO_MASK(CAP_SETGID);
+    cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].effective |= CAP_TO_MASK(CAP_WAKE_ALARM);
+
+    capset(&header, &cap[0]);
+    setgroups(sizeof(groups)/sizeof(groups[0]), groups);
+}
+
+
+
+/*****************************************************************************
+**   Logger API
+*****************************************************************************/
+
+void bdt_log(const char *fmt_str, ...)
+{
+    static char buffer[1024];
+    va_list ap;
+
+    va_start(ap, fmt_str);
+    vsnprintf(buffer, 1024, fmt_str, ap);
+    va_end(ap);
+
+    fprintf(stdout, "%s\n", buffer);
+}
+
+/*******************************************************************************
+ ** Misc helper functions
+ *******************************************************************************/
+static const char* dump_bt_status(bt_status_t status)
+{
+    switch(status)
+    {
+        CASE_RETURN_STR(BT_STATUS_SUCCESS)
+        CASE_RETURN_STR(BT_STATUS_FAIL)
+        CASE_RETURN_STR(BT_STATUS_NOT_READY)
+        CASE_RETURN_STR(BT_STATUS_NOMEM)
+        CASE_RETURN_STR(BT_STATUS_BUSY)
+        CASE_RETURN_STR(BT_STATUS_UNSUPPORTED)
+
+        default:
+            return "unknown status code";
+    }
+}
+#if 0
+static void hex_dump(char *msg, void *data, int size, int trunc)
+{
+    unsigned char *p = data;
+    unsigned char c;
+    int n;
+    char bytestr[4] = {0};
+    char addrstr[10] = {0};
+    char hexstr[ 16*3 + 5] = {0};
+    char charstr[16*1 + 5] = {0};
+
+    bdt_log("%s  \n", msg);
+
+    /* truncate */
+    if(trunc && (size>32))
+        size = 32;
+
+    for(n=1;n<=size;n++) {
+        if (n%16 == 1) {
+            /* store address for this line */
+            snprintf(addrstr, sizeof(addrstr), "%.4x",
+               ((unsigned int)p-(unsigned int)data) );
+        }
+
+        c = *p;
+        if (isalnum(c) == 0) {
+            c = '.';
+        }
+
+        /* store hex str (for left side) */
+        snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
+        strlcat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
+
+        /* store char str (for right side) */
+        snprintf(bytestr, sizeof(bytestr), "%c", c);
+        strlcat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
+
+        if(n%16 == 0) {
+            /* line completed */
+            bdt_log("[%4.4s]   %-50.50s  %s\n", addrstr, hexstr, charstr);
+            hexstr[0] = 0;
+            charstr[0] = 0;
+        } else if(n%8 == 0) {
+            /* half line: add whitespaces */
+            strlcat(hexstr, "  ", sizeof(hexstr)-strlen(hexstr)-1);
+            strlcat(charstr, " ", sizeof(charstr)-strlen(charstr)-1);
+        }
+        p++; /* next byte */
+    }
+
+    if (strlen(hexstr) > 0) {
+        /* print rest of buffer if not empty */
+        bdt_log("[%4.4s]   %-50.50s  %s\n", addrstr, hexstr, charstr);
+    }
+}
+#endif
+
+/*******************************************************************************
+ ** Console helper functions
+ *******************************************************************************/
+
+void skip_blanks(char **p)
+{
+  while (**p == ' ')
+    (*p)++;
+}
+
+uint32_t get_int(char **p, int DefaultValue)
+{
+  uint32_t Value = 0;
+  unsigned char   UseDefault;
+
+  UseDefault = 1;
+  skip_blanks(p);
+
+  while ( ((**p)<= '9' && (**p)>= '0') )
+    {
+      Value = Value * 10 + (**p) - '0';
+      UseDefault = 0;
+      (*p)++;
+    }
+
+  if (UseDefault)
+    return DefaultValue;
+  else
+    return Value;
+}
+
+int get_signed_int(char **p, int DefaultValue)
+{
+  int    Value = 0;
+  unsigned char   UseDefault;
+  unsigned char  NegativeNum = 0;
+
+  UseDefault = 1;
+  skip_blanks(p);
+
+  if ( (**p) == '-')
+    {
+      NegativeNum = 1;
+      (*p)++;
+    }
+  while ( ((**p)<= '9' && (**p)>= '0') )
+    {
+      Value = Value * 10 + (**p) - '0';
+      UseDefault = 0;
+      (*p)++;
+    }
+
+  if (UseDefault)
+    return DefaultValue;
+  else
+    return ((NegativeNum == 0)? Value : -Value);
+}
+
+void get_str(char **p, char *Buffer)
+{
+  skip_blanks(p);
+
+  while (**p != 0 && **p != ' ')
+    {
+      *Buffer = **p;
+      (*p)++;
+      Buffer++;
+    }
+
+  *Buffer = 0;
+}
+
+uint32_t get_hex_any(char **p, int DefaultValue, unsigned int NumOfNibble)
+{
+  uint32_t Value = 0;
+  unsigned char   UseDefault;
+  //unsigned char   NumOfNibble = 8;	//Since we are returning uint32, max allowed is 4 bytes(8 nibbles).
+
+  UseDefault = 1;
+  skip_blanks(p);
+
+  while ((NumOfNibble) && (((**p)<= '9' && (**p)>= '0') ||
+          ((**p)<= 'f' && (**p)>= 'a') ||
+          ((**p)<= 'F' && (**p)>= 'A')) )
+    {
+      if (**p >= 'a')
+        Value = Value * 16 + (**p) - 'a' + 10;
+      else if (**p >= 'A')
+        Value = Value * 16 + (**p) - 'A' + 10;
+      else
+        Value = Value * 16 + (**p) - '0';
+      UseDefault = 0;
+      (*p)++;
+      NumOfNibble--;
+    }
+
+  if (UseDefault)
+    return DefaultValue;
+  else
+    return Value;
+}
+uint32_t get_hex(char **p, int DefaultValue)
+{
+    //unsigned char   NumOfNibble = 8;	//Since we are returning uint32, max allowed is 4 bytes(8 nibbles).
+   return (get_hex_any(p, DefaultValue, 8));
+}
+uint32_t get_hex_byte(char **p, int DefaultValue)
+{
+   return (get_hex_any(p, DefaultValue, 2));
+}
+
+void get_bdaddr(const char *str, bt_bdaddr_t *bd) {
+    char *d = ((char *)bd), *endp;
+    int i;
+    for(i = 0; i < 6; i++) {
+        *d++ = strtol(str, &endp, 16);
+        if (*endp != ':' && i != 5) {
+            memset(bd, 0, sizeof(bt_bdaddr_t));
+            return;
+        }
+        str = endp + 1;
+    }
+}
+
+#define is_cmd(str) ((strlen(str) == strlen(cmd)) && strncmp((const char *)&cmd, str, strlen(str)) == 0)
+#define if_cmd(str)  if (is_cmd(str))
+
+typedef void (t_console_cmd_handler) (char *p);
+
+typedef struct {
+    const char *name;
+    t_console_cmd_handler *handler;
+    const char *help;
+    unsigned char is_job;
+} t_cmd;
+
+
+const t_cmd console_cmd_list[];
+static int console_cmd_maxlen = 0;
+
+static void cmdjob_handler(void *param)
+{
+    char *job_cmd = (char*)param;
+
+    bdt_log("cmdjob starting (%s)", job_cmd);
+
+    process_cmd(job_cmd, 1);
+
+    bdt_log("cmdjob terminating");
+
+    free(job_cmd);
+}
+
+static int create_cmdjob(char *cmd)
+{
+    pthread_t thread_id;
+    char *job_cmd;
+    job_cmd = (char*)calloc(1, strlen(cmd)+1); /* freed in job handler */
+    if(job_cmd)
+    {
+        strlcpy(job_cmd, cmd, strlen(job_cmd)+1);
+
+        if (pthread_create(&thread_id, NULL,
+                       (void*)cmdjob_handler, (void*)job_cmd)!=0)
+        perror("pthread_create");
+    }
+    else
+        bdt_log("Mecap_test: Cannot Allocate memory for cmdjob");
+
+
+    return 0;
+}
+
+/*******************************************************************************
+ ** Load stack lib
+ *******************************************************************************/
+
+int HAL_load(void)
+{
+    int err = 0;
+
+    hw_module_t* module;
+    hw_device_t* device;
+
+    bdt_log("Loading HAL lib + extensions");
+
+    err = hw_get_module(BT_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
+    if (err == 0)
+    {
+        err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
+        if (err == 0) {
+            bt_device = (bluetooth_device_t *)device;
+            sBtInterface = bt_device->get_bluetooth_interface();
+        }
+    }
+
+    bdt_log("HAL library loaded (%s)", strerror(err));
+
+    return err;
+}
+
+int HAL_unload(void)
+{
+    int err = 0;
+
+    bdt_log("Unloading HAL lib");
+
+    sBtInterface = NULL;
+
+    bdt_log("HAL library unloaded (%s)", strerror(err));
+
+    return err;
+}
+
+/*******************************************************************************
+ ** HAL test functions & callbacks
+ *******************************************************************************/
+
+void setup_test_env(void)
+{
+    int i = 0;
+
+    while (console_cmd_list[i].name != NULL)
+    {
+        console_cmd_maxlen = MAX(console_cmd_maxlen, (int)strlen(console_cmd_list[i].name));
+        i++;
+    }
+}
+
+void check_return_status(bt_status_t status)
+{
+    if (status != BT_STATUS_SUCCESS)
+    {
+        bdt_log("HAL REQUEST FAILED status : %d (%s)", status, dump_bt_status(status));
+    }
+    else
+    {
+        bdt_log("HAL REQUEST SUCCESS");
+    }
+}
+
+static void adapter_state_changed(bt_state_t state)
+{
+    int V1 = 1000, V2=2;
+    bt_property_t property = {9 /*BT_PROPERTY_DISCOVERY_TIMEOUT*/, 4, &V1};
+    bt_property_t property1 = {7 /*SCAN*/, 2, &V2};
+    bt_property_t property2 ={1,6,"Bluedroid"};
+
+    g_AdapterState = state;
+
+    if (state == BT_STATE_ON) {
+        bt_enabled = 1;
+        status = sBtInterface->set_adapter_property(&property1);
+        status = sBtInterface->set_adapter_property(&property);
+        status = sBtInterface->set_adapter_property(&property2);
+    }
+    else {
+       bt_enabled = 0;
+    }
+}
+
+static void adapter_properties_changed(bt_status_t status, int num_properties, bt_property_t *properties)
+{
+    char Bd_addr[15] = {0};
+    if(NULL == properties)
+    {
+        printf("properties is null\n");
+        return;
+    }
+    switch(properties->type)
+    {
+        case BT_PROPERTY_BDADDR:
+        memcpy(Bd_addr, properties->val, properties->len);
+        printf("Local Bd Addr = %02x:%02x:%02x:%02x:%02x:%02x\n", Bd_addr[0], Bd_addr[1], Bd_addr[2], Bd_addr[3], Bd_addr[4], Bd_addr[5]);
+        break;
+        default :
+        break;
+    }
+    return;
+}
+
+static void discovery_state_changed(bt_discovery_state_t state)
+{
+    printf("Discovery State Updated : %s\n", (state == BT_DISCOVERY_STOPPED)?"STOPPED":"STARTED");
+}
+
+
+static void pin_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name, uint32_t cod, bool min_16_digit)
+{
+    bt_pin_code_t pincode = {{ 0x31, 0x32, 0x33, 0x34}};
+
+    if(BT_STATUS_SUCCESS != sBtInterface->pin_reply(remote_bd_addr, TRUE, 4, &pincode))
+    {
+        printf("Pin Reply failed\n");
+    }
+}
+
+static void ssp_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name,
+                           uint32_t cod, bt_ssp_variant_t pairing_variant, uint32_t pass_key)
+{
+    printf("ssp_request_cb : %s %d %u\n", bd_name->name, pairing_variant, pass_key);
+    if(BT_STATUS_SUCCESS != sBtInterface->ssp_reply(remote_bd_addr, pairing_variant, TRUE, pass_key))
+    {
+        printf("SSP Reply failed\n");
+    }
+}
+
+static void bond_state_changed_cb(bt_status_t status, bt_bdaddr_t *remote_bd_addr, bt_bond_state_t state)
+{
+    printf("Bond State Changed = %d\n", state);
+    g_PairState = state;
+}
+
+static void acl_state_changed(bt_status_t status, bt_bdaddr_t *remote_bd_addr, bt_acl_state_t state)
+{
+    printf("acl_state_changed : remote_bd_addr=%02x:%02x:%02x:%02x:%02x:%02x, acl status=%s \n",
+    remote_bd_addr->address[0], remote_bd_addr->address[1], remote_bd_addr->address[2],
+    remote_bd_addr->address[3], remote_bd_addr->address[4], remote_bd_addr->address[5],
+    (state == BT_ACL_STATE_CONNECTED)?"ACL Connected" :"ACL Disconnected"
+    );
+}
+
+
+static void dut_mode_recv(uint16_t opcode, uint8_t *buf, uint8_t len)
+{
+    bdt_log("DUT MODE RECV : NOT IMPLEMENTED");
+}
+
+static void le_test_mode(bt_status_t status, uint16_t packet_count)
+{
+    bdt_log("LE TEST MODE END status:%s number_of_packets:%d", dump_bt_status(status), packet_count);
+}
+
+static bt_callbacks_t bt_callbacks = {
+    sizeof(bt_callbacks_t),
+    adapter_state_changed,
+    adapter_properties_changed, /*adapter_properties_cb */
+    NULL, /* remote_device_properties_cb */
+    NULL, /* device_found_cb */
+    discovery_state_changed, /* discovery_state_changed_cb */
+    pin_request_cb, /* pin_request_cb  */
+    ssp_request_cb, /* ssp_request_cb  */
+    bond_state_changed_cb, /*bond_state_changed_cb */
+    acl_state_changed, /* acl_state_changed_cb */
+    NULL, /* thread_evt_cb */
+    dut_mode_recv, /*dut_mode_recv_cb */
+
+  //    NULL, /*authorize_request_cb */
+#if BLE_INCLUDED == TRUE
+    le_test_mode, /* le_test_mode_cb */
+#else
+    NULL,
+#endif
+    NULL,
+    NULL
+};
+
+static bool set_wake_alarm(uint64_t delay_millis, bool should_wake, alarm_cb cb, void *data) {
+  static timer_t timer;
+  static bool timer_created;
+
+  if (!timer_created) {
+    struct sigevent sigevent;
+    memset(&sigevent, 0, sizeof(sigevent));
+    sigevent.sigev_notify = SIGEV_THREAD;
+    sigevent.sigev_notify_function = (void (*)(union sigval))cb;
+    sigevent.sigev_value.sival_ptr = data;
+    timer_create(CLOCK_MONOTONIC, &sigevent, &timer);
+    timer_created = true;
+  }
+
+  struct itimerspec new_value;
+  new_value.it_value.tv_sec = delay_millis / 1000;
+  new_value.it_value.tv_nsec = (delay_millis % 1000) * 1000 * 1000;
+  new_value.it_interval.tv_sec = 0;
+  new_value.it_interval.tv_nsec = 0;
+  timer_settime(timer, 0, &new_value, NULL);
+
+  return true;
+}
+
+static int acquire_wake_lock(const char *lock_name) {
+  return BT_STATUS_SUCCESS;
+}
+
+static int release_wake_lock(const char *lock_name) {
+  return BT_STATUS_SUCCESS;
+}
+
+static bt_os_callouts_t callouts = {
+    sizeof(bt_os_callouts_t),
+    set_wake_alarm,
+    acquire_wake_lock,
+    release_wake_lock,
+};
+
+void bdt_init(void)
+{
+    bdt_log("INIT BT ");
+    status = sBtInterface->init(&bt_callbacks);
+     if (status == BT_STATUS_SUCCESS) {
+        status = sBtInterface->set_os_callouts(&callouts);
+    }
+    check_return_status(status);
+}
+
+void bdt_enable(void)
+{
+    bdt_log("ENABLE BT");
+    if (bt_enabled) {
+        bdt_log("Bluetooth is already enabled");
+        return;
+    }
+    status = sBtInterface->enable(strict_mode);
+
+    check_return_status(status);
+}
+
+void bdt_disable(void)
+{
+    bdt_log("DISABLE BT");
+    if (!bt_enabled) {
+        bdt_log("Bluetooth is already disabled");
+        return;
+    }
+    status = sBtInterface->disable();
+
+    check_return_status(status);
+}
+void bdt_dut_mode_configure(char *p)
+{
+    int32_t mode = -1;
+
+    bdt_log("BT DUT MODE CONFIGURE");
+    if (!bt_enabled) {
+        bdt_log("Bluetooth must be enabled for test_mode to work.");
+        return;
+    }
+    mode = get_signed_int(&p, mode);
+    if ((mode != 0) && (mode != 1)) {
+        bdt_log("Please specify mode: 1 to enter, 0 to exit");
+        return;
+    }
+    status = sBtInterface->dut_mode_configure(mode);
+
+    check_return_status(status);
+}
+
+#define HCI_LE_RECEIVER_TEST_OPCODE 0x201D
+#define HCI_LE_TRANSMITTER_TEST_OPCODE 0x201E
+#define HCI_LE_END_TEST_OPCODE 0x201F
+
+void bdt_le_test_mode(char *p)
+{
+    int cmd;
+    unsigned char buf[3];
+    int arg1, arg2, arg3;
+
+    bdt_log("BT LE TEST MODE");
+    if (!bt_enabled) {
+        bdt_log("Bluetooth must be enabled for le_test to work.");
+        return;
+    }
+
+    memset(buf, 0, sizeof(buf));
+    cmd = get_int(&p, 0);
+    switch (cmd)
+    {
+        case 0x1: /* RX TEST */
+           arg1 = get_int(&p, -1);
+           if (arg1 < 0) bdt_log("%s Invalid arguments", __FUNCTION__);
+           buf[0] = arg1;
+           status = sBtInterface->le_test_mode(HCI_LE_RECEIVER_TEST_OPCODE, buf, 1);
+           break;
+        case 0x2: /* TX TEST */
+            arg1 = get_int(&p, -1);
+            arg2 = get_int(&p, -1);
+            arg3 = get_int(&p, -1);
+            if ((arg1 < 0) || (arg2 < 0) || (arg3 < 0))
+                bdt_log("%s Invalid arguments", __FUNCTION__);
+            buf[0] = arg1;
+            buf[1] = arg2;
+            buf[2] = arg3;
+            status = sBtInterface->le_test_mode(HCI_LE_TRANSMITTER_TEST_OPCODE, buf, 3);
+           break;
+        case 0x3: /* END TEST */
+            status = sBtInterface->le_test_mode(HCI_LE_END_TEST_OPCODE, buf, 0);
+           break;
+        default:
+            bdt_log("Unsupported command");
+            return;
+            break;
+    }
+    if (status != BT_STATUS_SUCCESS)
+    {
+        bdt_log("%s Test 0x%x Failed with status:0x%x", __FUNCTION__, cmd, status);
+    }
+    return;
+}
+
+void bdt_cleanup(void)
+{
+    bdt_log("CLEANUP");
+    sBtInterface->cleanup();
+}
+
+/*******************************************************************************
+ ** Console commands
+ *******************************************************************************/
+
+void do_help(char *p)
+{
+    int i = 0;
+    char line[128];
+    int pos = 0;
+
+    while (console_cmd_list[i].name != NULL)
+    {
+        pos = snprintf(line, sizeof(line), "%s", (char*)console_cmd_list[i].name);
+        bdt_log("%s %s\n", (char*)line, (char*)console_cmd_list[i].help);
+        i++;
+    }
+}
+
+void do_quit(char *p)
+{
+    bdt_shutdown();
+}
+
+/*******************************************************************
+ *
+ *  BT TEST  CONSOLE COMMANDS
+ *
+ *  Parses argument lists and passes to API test function
+ *
+*/
+
+void do_init(char *p)
+{
+    bdt_init();
+}
+
+void do_enable(char *p)
+{
+    bdt_enable();
+}
+
+void do_disable(char *p)
+{
+    bdt_disable();
+}
+
+void do_cleanup(char *p)
+{
+    bdt_cleanup();
+}
+
+
+/*******************************************************************************
+ ** MCAP API commands
+ *******************************************************************************/
+void do_mcap_register(char *p)
+{
+    tMCA_REG   Mca_Reg;
+    Mca_Reg.rsp_tout = 5000;   //Need to check if we have to give in msec or seconds
+    Mca_Reg.ctrl_psm = get_hex(&p, -1);  // arg1
+    Mca_Reg.data_psm = get_hex(&p, -1);  // arg2
+    Mca_Reg.sec_mask = get_int(&p, -1);  // arg3
+    g_Mcap_Handle = sMcapIface->Register(&Mca_Reg, mcap_ctrl_cb);
+    printf("%s:: Ret=%d \n", __FUNCTION__, g_Mcap_Handle);
+}
+
+void do_mcap_deregister(char *p)
+{
+    sMcapIface->Deregister(g_Mcap_Handle);
+    printf("%s:: Handle=%d \n", __FUNCTION__, g_Mcap_Handle);
+}
+
+void do_mcap_create_dep(char *p)
+{
+    tMCA_RESULT  Ret  = 0;
+    int         type  = 0;
+    tMCA_CS     Mca_cs ;
+    type    = get_int(&p, -1);  // arg1
+
+    memset ((void*)&Mca_cs ,0 ,sizeof(tMCA_CS));
+    Mca_cs.type   = (0 == type) ? MCA_TDEP_ECHO :MCA_TDEP_DATA;
+    Mca_cs.max_mdl  = MCA_NUM_MDLS;
+    Mca_cs.p_data_cback = mcap_data_cb;
+
+    Ret = sMcapIface->CreateDep(g_Mcap_Handle, &g_Mcap_Dep, &Mca_cs);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+
+static void do_mcap_delete_dep(char *p)
+{
+    tMCA_RESULT   Ret  = 0;
+    Ret = sMcapIface->DeleteDep(g_Mcap_Handle, g_Mcap_Dep);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+
+static void do_mcap_connect(char *p)
+{
+    tMCA_RESULT  Ret = 0;
+    bt_bdaddr_t bd_addr = {{0}};
+    UINT16      ctrl_psm = 0;
+    UINT16      sec_mask = 0;
+    char   buf[64];
+
+    get_str(&p, buf);
+    str2bd(buf, &bd_addr);
+    ctrl_psm  = get_hex(&p, -1);// arg2
+    sec_mask  = get_int(&p, -1);// arg3
+    printf("ctrl_psm=%d, secMask=%d \n", ctrl_psm, sec_mask);
+    Ret = sMcapIface->ConnectReq(g_Mcap_Handle, bd_addr.address, ctrl_psm, sec_mask);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+
+static void do_mcap_disconnect(char *p)
+{
+    tMCA_RESULT  Ret  = 0;
+    Ret = sMcapIface->DisconnectReq(g_Mcl);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+
+static void do_mcap_create_mdl(char *p)
+{
+    tMCA_RESULT Ret  = 0;
+    UINT16  data_psm = 0;
+    data_psm   = get_hex(&p, -1);  // arg1
+    Ret = sMcapIface->CreateMdl(g_Mcl, g_Mcap_Dep, data_psm, 1, 1, 1, &g_chnl_cfg);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+
+static void do_mcap_close(char *p)
+{
+    tMCA_RESULT  Ret  = 0;
+    Ret = sMcapIface->CloseReq(g_Mdl);
+    printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
+}
+
+static void do_pairing(char *p)
+{
+    bt_bdaddr_t bd_addr = {{0}};
+
+    if(FALSE == GetBdAddr(p, &bd_addr))
+        return; // arg1
+    if(BT_STATUS_SUCCESS != sBtInterface->create_bond(&bd_addr, TRANSPORT_BREDR))
+    {
+        printf("Failed to Initiate Pairing \n");
+        return;
+    }
+}
+
+/*******************************************************************
+ *
+ *  CONSOLE COMMAND TABLE
+ *
+*/
+
+const t_cmd console_cmd_list[] =
+{
+    /*
+     * INTERNAL
+     */
+
+    { "help", do_help, "lists all available console commands", 0 },
+    { "quit", do_quit, "", 0},
+
+    /*
+     * API CONSOLE COMMANDS
+     */
+
+     /* Init and Cleanup shall be called automatically */
+    { "enable", do_enable, ":: enables bluetooth", 0 },
+    { "disable", do_disable, ":: disables bluetooth", 0 },
+    { "pair", do_pairing, ":: BdAddr<00112233445566>", 0 },
+    { "register", do_mcap_register, "::Ctrl_Psm<hex>, Data_Psm<hex>, Security<0-10>", 0 },
+    { "deregister", do_mcap_deregister, "::", 0 },
+    { "create_data_endpoint", do_mcap_create_dep, "::Type<0-Echo, 1-NormalData>", 0 },
+    { "delete_data_endpoint", do_mcap_delete_dep, "::", 0 },
+    { "connect", do_mcap_connect, ":: BdAddr<00112233445566>, Ctrl_Psm<hex>, SecMask<int>", 0 },
+    { "disconnect", do_mcap_disconnect, ":: BdAddr<00112233445566>", 0 },
+    { "create_mdl", do_mcap_create_mdl, ":: Data_Psm<hex>", 0 },
+    { "close_data_channel", do_mcap_close, "::", 0 },
+    /* last entry */
+    {NULL, NULL, "", 0},
+};
+
+/*
+ * Main console command handler
+*/
+
+static void process_cmd(char *p, unsigned char is_job)
+{
+    char cmd[2048];
+    int i = 0;
+    char *p_saved = p;
+
+    get_str(&p, cmd);
+
+    /* table commands */
+    while (console_cmd_list[i].name != NULL)
+    {
+        if (is_cmd(console_cmd_list[i].name))
+        {
+            if (!is_job && console_cmd_list[i].is_job)
+                create_cmdjob(p_saved);
+            else
+            {
+                console_cmd_list[i].handler(p);
+            }
+            return;
+        }
+        i++;
+    }
+    bdt_log("%s : unknown command\n", p_saved);
+    do_help(NULL);
+}
+
+int main (int argc, char * argv[])
+{
+
+    config_permissions();
+    bdt_log("\n:::::::::::::::::::::::::::::::::::::::::::::::::::");
+    bdt_log(":: Bluedroid test app starting");
+
+    if ( HAL_load() < 0 ) {
+        perror("HAL failed to initialize, exit\n");
+        unlink(PID_FILE);
+        exit(0);
+    }
+
+    setup_test_env();
+
+    /* Automatically perform the init */
+    bdt_init();
+    sleep(5);
+    bdt_enable();
+    sleep(5);
+
+    sMcapIface  = (btmcap_interface_t *)sBtInterface->get_testapp_interface(TEST_APP_MCAP);
+    //sSmpIface = sBtInterface->get_testapp_interface(TEST_APP_SMP);
+    sleep(1);
+    sMcapIface->Init();
+
+    while(!main_done)
+    {
+        char line[2048];
+
+        /* command prompt */
+        printf( ">" );
+        fflush(stdout);
+
+        fgets (line, 2048, stdin);
+
+        if (line[0]!= '\0')
+        {
+            /* remove linefeed */
+            line[strlen(line)-1] = 0;
+
+            process_cmd(line, 0);
+            memset(line, '\0', 2048);
+        }
+    }
+
+    /* FIXME: Commenting this out as for some reason, the application does not exit otherwise*/
+    //bdt_cleanup();
+
+    HAL_unload();
+
+    bdt_log(":: Bluedroid test app terminating");
+
+    return 0;
+}
+
+
+int GetBdAddr(char *p, bt_bdaddr_t *pbd_addr)
+{
+    char Arr[13] = {0};
+    UINT8 k1 = 0;
+    UINT8 k2 = 0;
+    int i;
+
+    if(12 != strlen(p))
+    {
+        printf("\nInvalid Bd Address. Format[112233445566]\n");
+        return FALSE;
+    }
+    strlcpy(Arr, p, sizeof(Arr));
+    for(i=0; i<12; i++)
+    {
+        Arr[i] = tolower(Arr[i]);
+    }
+    for(i=0; i<6; i++)
+    {
+        k1 = (UINT8) ( (Arr[i*2] >= 'a') ? ( 10 + (UINT8)( Arr[i*2] - 'a' )) : (Arr[i*2] - '0') );
+        k2 = (UINT8) ( (Arr[(i*2)+1] >= 'a') ? ( 10 + (UINT8)( Arr[(i*2)+1] - 'a' )) : (Arr[(i*2)+1] - '0') );
+        if ( (k1>15)||(k2>15) )
+        {
+            return FALSE;
+        }
+        pbd_addr->address[i] = (k1<<4 | k2);
+    }
+    return TRUE;
+}
diff --git a/test/rfcommtest/Android.mk b/test/rfcommtest/Android.mk
new file mode 100644
index 0000000..f4ae2ca
--- /dev/null
+++ b/test/rfcommtest/Android.mk
@@ -0,0 +1,33 @@
+#
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=     \
+    rfcommtest.c
+
+LOCAL_C_INCLUDES += . \
+        $(LOCAL_PATH)/../../stack/include \
+        $(LOCAL_PATH)/../../include \
+        $(LOCAL_PATH)/../../stack/l2cap \
+        $(LOCAL_PATH)/../../utils/include \
+        $(LOCAL_PATH)/../../ \
+        $(LOCAL_PATH)/btif/include \
+        $(bluetooth_C_INCLUDES)
+
+LOCAL_CFLAGS += $(bluetooth_CFLAGS)
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
+LOCAL_MODULE_TAGS := debug optional
+LOCAL_MODULE:= rfc
+
+LOCAL_SHARED_LIBRARIES += libcutils   \
+                          libutils    \
+                          libhardware \
+                          libhardware_legacy
+
+LOCAL_MULTILIB := 32
+
+include $(BUILD_EXECUTABLE)
diff --git a/test/rfcommtest/rfcommtest.c b/test/rfcommtest/rfcommtest.c
new file mode 100644
index 0000000..2159daf
--- /dev/null
+++ b/test/rfcommtest/rfcommtest.c
@@ -0,0 +1,1100 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014, The linux Foundation. All rights reserved.
+ *
+ *  Not a Contribution.
+ *
+ *  Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/************************************************************************************
+ *
+ *  Filename:      rfcommtest.c
+ *
+ *  Description:   RFCOMM Test application
+ *
+ ***********************************************************************************/
+
+#include <stdio.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/prctl.h>
+#include <sys/capability.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <private/android_filesystem_config.h>
+#include <android/log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/bluetooth.h>
+#include "bt_target.h"
+#include "bt_testapp.h"
+
+/************************************************************************************
+**  Constants & Macros
+************************************************************************************/
+
+#define PID_FILE "/data/.bdt_pid"
+
+#ifndef MAX
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+#endif
+
+#define CASE_RETURN_STR(const) case const: return #const;
+#define DISCONNECT 3
+
+/************************************************************************************
+**  Local type definitions
+************************************************************************************/
+
+/************************************************************************************
+**  Static variables
+************************************************************************************/
+
+static unsigned char main_done = 0;
+static bt_status_t status;
+
+/* Main API */
+static bluetooth_device_t* bt_device;
+
+const bt_interface_t* sBtInterface = NULL;
+const btrfcomm_interface_t *sRfcInterface = NULL;
+
+static gid_t groups[] = { AID_NET_BT, AID_INET, AID_NET_BT_ADMIN,
+                          AID_SYSTEM, AID_MISC, AID_SDCARD_RW,
+                          AID_NET_ADMIN, AID_VPN};
+
+/* Set to 1 when the Bluedroid stack is enabled */
+static unsigned char bt_enabled = 0;
+static bool strict_mode = FALSE;
+
+/************************************************************************************
+**  Static functions
+************************************************************************************/
+
+static void process_cmd(char *p, unsigned char is_job);
+static void bdt_log(const char *fmt_str, ...);
+
+
+/************************************************************************************
+**  Externs
+************************************************************************************/
+
+/************************************************************************************
+**  Functions
+************************************************************************************/
+
+
+/************************************************************************************
+**  Shutdown helper functions
+************************************************************************************/
+
+static void bdt_shutdown(void)
+{
+    bdt_log("shutdown bdroid test app\n");
+    main_done = 1;
+}
+
+
+/*****************************************************************************
+** Android's init.rc does not yet support applying linux capabilities
+*****************************************************************************/
+
+static int str2bd(char *str, bt_bdaddr_t *addr)
+{
+    int32_t i = 0;
+
+    for (i = 0; i < 6; i++)
+    {
+        addr->address[i] = (uint8_t) strtoul(str, (char **)&str, 16);
+        str++;
+    }
+    return 0;
+}
+static void config_permissions(void)
+{
+    struct __user_cap_header_struct header;
+    struct __user_cap_data_struct cap[2];
+
+    bdt_log("set_aid_and_cap : pid %d, uid %d gid %d", getpid(), getuid(), getgid());
+
+    header.pid = 0;
+
+    prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+
+    setuid(AID_BLUETOOTH);
+    setgid(AID_BLUETOOTH);
+
+    header.version = _LINUX_CAPABILITY_VERSION_3;
+
+    cap[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW);
+    cap[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN);
+    cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].permitted |= CAP_TO_MASK(CAP_NET_BIND_SERVICE);
+    cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].permitted |= CAP_TO_MASK(CAP_SYS_RAWIO);
+    cap[CAP_TO_INDEX(CAP_SYS_NICE)].permitted |= CAP_TO_MASK(CAP_SYS_NICE);
+    cap[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
+    cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].permitted |= CAP_TO_MASK(CAP_WAKE_ALARM);
+
+    cap[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW);
+    cap[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN);
+    cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].effective |= CAP_TO_MASK(CAP_NET_BIND_SERVICE);
+    cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].effective |= CAP_TO_MASK(CAP_SYS_RAWIO);
+    cap[CAP_TO_INDEX(CAP_SYS_NICE)].effective |= CAP_TO_MASK(CAP_SYS_NICE);
+    cap[CAP_TO_INDEX(CAP_SETGID)].effective |= CAP_TO_MASK(CAP_SETGID);
+    cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].effective |= CAP_TO_MASK(CAP_WAKE_ALARM);
+
+    capset(&header, &cap[0]);
+    setgroups(sizeof(groups)/sizeof(groups[0]), groups);
+}
+#if 0
+/*Pin_Request_cb */
+static void pin_remote_request_callback (bt_bdaddr_t *remote_bd_addr,
+                             bt_bdname_t *bd_name, uint32_t cod)
+{
+    bt_pin_code_t    pin_code;
+    /* Default 1234 is the Pin code */
+    pin_code.pin[0]  =  0x31;
+    pin_code.pin[1]  =  0x32;
+    pin_code.pin[2]  =  0x33;
+    pin_code.pin[3]  =  0x34;
+
+    bdt_log("bdt PIN Remote Request");
+    sBtInterface->pin_reply(remote_bd_addr ,1 , 4 , &pin_code);
+}
+#endif
+
+/* Pairing in Case of SSP */
+static void ssp_remote_requst_callback(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name,
+                             uint32_t cod, bt_ssp_variant_t pairing_variant, uint32_t pass_key)
+{
+    if (pairing_variant == BT_SSP_VARIANT_PASSKEY_ENTRY)
+    {
+        bdt_log("bdt ssp remote request not supported");
+        return;
+    }
+    bdt_log("bdt accept SSP pairing");
+    sBtInterface->ssp_reply(remote_bd_addr,  pairing_variant, 1,  pass_key);
+}
+
+
+
+
+/*****************************************************************************
+**   Logger API
+*****************************************************************************/
+
+void bdt_log(const char *fmt_str, ...)
+{
+    static char buffer[1024];
+    va_list ap;
+
+    va_start(ap, fmt_str);
+    vsnprintf(buffer, 1024, fmt_str, ap);
+    va_end(ap);
+
+    fprintf(stdout, "%s\n", buffer);
+}
+
+/*******************************************************************************
+ ** Misc helper functions
+ *******************************************************************************/
+static const char* dump_bt_status(bt_status_t status)
+{
+    switch(status)
+    {
+        CASE_RETURN_STR(BT_STATUS_SUCCESS)
+        CASE_RETURN_STR(BT_STATUS_FAIL)
+        CASE_RETURN_STR(BT_STATUS_NOT_READY)
+        CASE_RETURN_STR(BT_STATUS_NOMEM)
+        CASE_RETURN_STR(BT_STATUS_BUSY)
+        CASE_RETURN_STR(BT_STATUS_UNSUPPORTED)
+
+        default:
+            return "unknown status code";
+    }
+}
+#if 0
+static void hex_dump(char *msg, void *data, int size, int trunc)
+{
+    unsigned char *p = data;
+    unsigned char c;
+    int n;
+    char bytestr[4] = {0};
+    char addrstr[10] = {0};
+    char hexstr[ 16*3 + 5] = {0};
+    char charstr[16*1 + 5] = {0};
+
+    bdt_log("%s  \n", msg);
+
+    /* truncate */
+    if(trunc && (size>32))
+        size = 32;
+
+    for(n=1;n<=size;n++) {
+        if (n%16 == 1) {
+            /* store address for this line */
+            snprintf(addrstr, sizeof(addrstr), "%.4x",
+               (unsigned int)((uintptr_t)p-(uintptr_t)data) );
+        }
+
+        c = *p;
+        if (isalnum(c) == 0) {
+            c = '.';
+        }
+
+        /* store hex str (for left side) */
+        snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
+        strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
+
+        /* store char str (for right side) */
+        snprintf(bytestr, sizeof(bytestr), "%c", c);
+        strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
+
+        if(n%16 == 0) {
+            /* line completed */
+            bdt_log("[%4.4s]   %-50.50s  %s\n", addrstr, hexstr, charstr);
+            hexstr[0] = 0;
+            charstr[0] = 0;
+        } else if(n%8 == 0) {
+            /* half line: add whitespaces */
+            strncat(hexstr, "  ", sizeof(hexstr)-strlen(hexstr)-1);
+            strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1);
+        }
+        p++; /* next byte */
+    }
+
+    if (strlen(hexstr) > 0) {
+        /* print rest of buffer if not empty */
+        bdt_log("[%4.4s]   %-50.50s  %s\n", addrstr, hexstr, charstr);
+    }
+}
+#endif
+/*******************************************************************************
+ ** Console helper functions
+ *******************************************************************************/
+
+void skip_blanks(char **p)
+{
+  while (**p == ' ')
+    (*p)++;
+}
+
+uint32_t get_int(char **p, int DefaultValue)
+{
+  uint32_t Value = 0;
+  unsigned char   UseDefault;
+
+  UseDefault = 1;
+  skip_blanks(p);
+
+  while ( ((**p)<= '9' && (**p)>= '0') )
+    {
+      Value = Value * 10 + (**p) - '0';
+      UseDefault = 0;
+      (*p)++;
+    }
+
+  if (UseDefault)
+    return DefaultValue;
+  else
+    return Value;
+}
+
+int get_signed_int(char **p, int DefaultValue)
+{
+  int    Value = 0;
+  unsigned char   UseDefault;
+  unsigned char  NegativeNum = 0;
+
+  UseDefault = 1;
+  skip_blanks(p);
+
+  if ( (**p) == '-')
+    {
+      NegativeNum = 1;
+      (*p)++;
+    }
+  while ( ((**p)<= '9' && (**p)>= '0') )
+    {
+      Value = Value * 10 + (**p) - '0';
+      UseDefault = 0;
+      (*p)++;
+    }
+
+  if (UseDefault)
+    return DefaultValue;
+  else
+    return ((NegativeNum == 0)? Value : -Value);
+}
+
+void get_str(char **p, char *Buffer)
+{
+  skip_blanks(p);
+
+  while (**p != 0 && **p != ' ')
+    {
+      *Buffer = **p;
+      (*p)++;
+      Buffer++;
+    }
+
+  *Buffer = 0;
+}
+
+uint32_t get_hex(char **p, int DefaultValue)
+{
+  uint32_t Value = 0;
+  unsigned char   UseDefault;
+
+  UseDefault = 1;
+  skip_blanks(p);
+
+  while ( ((**p)<= '9' && (**p)>= '0') ||
+          ((**p)<= 'f' && (**p)>= 'a') ||
+          ((**p)<= 'F' && (**p)>= 'A') )
+    {
+      if (**p >= 'a')
+        Value = Value * 16 + (**p) - 'a' + 10;
+      else if (**p >= 'A')
+        Value = Value * 16 + (**p) - 'A' + 10;
+      else
+        Value = Value * 16 + (**p) - '0';
+      UseDefault = 0;
+      (*p)++;
+    }
+
+  if (UseDefault)
+    return DefaultValue;
+  else
+    return Value;
+}
+
+void get_bdaddr(const char *str, bt_bdaddr_t *bd) {
+    char *d = ((char *)bd), *endp;
+    int i;
+    for(i = 0; i < 6; i++) {
+        *d++ = strtol(str, &endp, 16);
+        if (*endp != ':' && i != 5) {
+            memset(bd, 0, sizeof(bt_bdaddr_t));
+            return;
+        }
+        str = endp + 1;
+    }
+}
+
+#define is_cmd(str) ((strlen(str) == strlen(cmd)) && strncmp((const char *)&cmd, str, strlen(str)) == 0)
+#define if_cmd(str)  if (is_cmd(str))
+
+typedef void (t_console_cmd_handler) (char *p);
+
+typedef struct {
+    const char *name;
+    t_console_cmd_handler *handler;
+    const char *help;
+    unsigned char is_job;
+} t_cmd;
+
+
+const t_cmd console_cmd_list[];
+static int console_cmd_maxlen = 0;
+
+static void cmdjob_handler(void *param)
+{
+    char *job_cmd = (char*)param;
+
+    bdt_log("cmdjob starting (%s)", job_cmd);
+
+    process_cmd(job_cmd, 1);
+
+    bdt_log("cmdjob terminating");
+
+    free(job_cmd);
+}
+
+static int create_cmdjob(char *cmd)
+{
+    pthread_t thread_id;
+    char *job_cmd;
+
+    job_cmd = (char*)calloc(1, strlen(cmd)+1); /* freed in job handler */
+    if (job_cmd)
+    {
+        strlcpy(job_cmd, cmd, sizeof(job_cmd));
+        if (pthread_create(&thread_id, NULL,
+                           (void*)cmdjob_handler, (void*)job_cmd)!=0)
+            perror("pthread_create");
+    }
+    else
+        bdt_log("Rfcomm_test: Cannot allocate memory for cmdjob");
+    return 0;
+}
+
+/*******************************************************************************
+ ** Load stack lib
+ *******************************************************************************/
+
+int HAL_load(void)
+{
+    int err = 0;
+
+    hw_module_t* module;
+    hw_device_t* device;
+
+    bdt_log("Loading HAL lib + extensions");
+
+    err = hw_get_module(BT_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
+    if (err == 0)
+    {
+        err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
+        if (err == 0) {
+            bt_device = (bluetooth_device_t *)device;
+            sBtInterface = bt_device->get_bluetooth_interface();
+        }
+    }
+
+    bdt_log("HAL library loaded (%s)", strerror(err));
+
+    return err;
+}
+
+int HAL_unload(void)
+{
+    int err = 0;
+
+    bdt_log("Unloading HAL lib");
+
+    sBtInterface = NULL;
+    sRfcInterface = NULL;
+
+    bdt_log("HAL library unloaded (%s)", strerror(err));
+
+    return err;
+}
+
+/*******************************************************************************
+ ** HAL test functions & callbacks
+ *******************************************************************************/
+
+void setup_test_env(void)
+{
+    int i = 0;
+
+    while (console_cmd_list[i].name != NULL)
+    {
+        console_cmd_maxlen = MAX(console_cmd_maxlen, (int)strlen(console_cmd_list[i].name));
+        i++;
+    }
+}
+
+void check_return_status(bt_status_t status)
+{
+    if (status != BT_STATUS_SUCCESS)
+    {
+        bdt_log("HAL REQUEST FAILED status : %d (%s)", status, dump_bt_status(status));
+    }
+    else
+    {
+        bdt_log("HAL REQUEST SUCCESS");
+    }
+}
+
+static void adapter_state_changed(bt_state_t state)
+{
+    bdt_log("ADAPTER STATE UPDATED : %s", (state == BT_STATE_OFF)?"OFF":"ON");
+    if (state == BT_STATE_ON) {
+        bt_enabled = 1;
+    } else {
+        bt_enabled = 0;
+    }
+}
+
+static void dut_mode_recv(uint16_t opcode, uint8_t *buf, uint8_t len)
+{
+    bdt_log("DUT MODE RECV : NOT IMPLEMENTED");
+}
+
+static void le_test_mode(bt_status_t status, uint16_t packet_count)
+{
+    bdt_log("LE TEST MODE END status:%s number_of_packets:%d", dump_bt_status(status), packet_count);
+}
+
+static void device_found_cb(int num_properties, bt_property_t *properties)
+{
+    int i;
+    for (i = 0; i < num_properties; i++)
+    {
+        if (properties[i].type == BT_PROPERTY_BDNAME)
+        {
+            bdt_log("AP name is : %s\n",
+                    (char*)properties[i].val);
+        }
+    }
+}
+
+static bt_callbacks_t bt_callbacks = {
+    sizeof(bt_callbacks_t),
+    adapter_state_changed,
+    NULL,                        /*adapter_properties_cb */
+    NULL,                        /* remote_device_properties_cb */
+    device_found_cb,             /* device_found_cb */
+    NULL,                        /* discovery_state_changed_cb */
+    NULL,                        /* pin_request_cb  */
+    ssp_remote_requst_callback,  /* ssp_request_cb  */
+    NULL,                        /*bond_state_changed_cb */
+    NULL,                        /* acl_state_changed_cb */
+    NULL,                        /* thread_evt_cb */
+    dut_mode_recv,               /*dut_mode_recv_cb */
+//    NULL,                      /*authorize_request_cb */
+#if BLE_INCLUDED == TRUE
+    le_test_mode,                /* le_test_mode_cb */
+#else
+    NULL,
+#endif
+    NULL,                       /* energy_info_cb */
+    NULL                        /* get_testapp_interface */
+};
+
+static bool set_wake_alarm(uint64_t delay_millis, bool should_wake, alarm_cb cb, void *data)
+{
+    static timer_t timer;
+    static bool timer_created;
+
+    if (!timer_created)
+    {
+        struct sigevent sigevent;
+        memset(&sigevent, 0, sizeof(sigevent));
+        sigevent.sigev_notify = SIGEV_THREAD;
+        sigevent.sigev_notify_function = (void (*)(union sigval))cb;
+        sigevent.sigev_value.sival_ptr = data;
+        timer_create(CLOCK_MONOTONIC, &sigevent, &timer);
+        timer_created = true;
+    }
+
+    struct itimerspec new_value;
+    new_value.it_value.tv_sec = delay_millis / 1000;
+    new_value.it_value.tv_nsec = (delay_millis % 1000) * 1000 * 1000;
+    new_value.it_interval.tv_sec = 0;
+    new_value.it_interval.tv_nsec = 0;
+    timer_settime(timer, 0, &new_value, NULL);
+
+    return true;
+}
+
+static int acquire_wake_lock(const char *lock_name)
+{
+    return BT_STATUS_SUCCESS;
+}
+
+static int release_wake_lock(const char *lock_name)
+{
+    return BT_STATUS_SUCCESS;
+}
+
+static bt_os_callouts_t callouts = {
+    sizeof(bt_os_callouts_t),
+    set_wake_alarm,
+    acquire_wake_lock,
+    release_wake_lock,
+};
+
+/* Rfcomm Client */
+void bdt_rfcomm(void)
+{
+    bdt_log("rfcomm client");
+
+    sRfcInterface = (btrfcomm_interface_t *)sBtInterface->get_testapp_interface(TEST_APP_RFCOMM);
+    if (sRfcInterface)
+    {
+       sRfcInterface->rdut_rfcomm(0);
+    }
+    else
+    {
+        bdt_log("interface not loaded");
+    }
+}
+
+/* Rfcomm  Server */
+void bdt_rfcomm_server (void)
+{
+    bdt_log("rfcomm server");
+
+    sRfcInterface = (btrfcomm_interface_t *)sBtInterface->get_testapp_interface(TEST_APP_RFCOMM);
+    if (sRfcInterface)
+    {
+        sRfcInterface->rdut_rfcomm(1);
+    }
+    else
+    {
+        bdt_log("interface not loaded");
+    }
+}
+
+/* Rfcomm disconnect */
+void bdt_rfcomm_disc_from_server(void)
+{
+    bdt_log("rfcomm disc from Server");
+
+    sRfcInterface = (btrfcomm_interface_t *)sBtInterface->get_testapp_interface(TEST_APP_RFCOMM);
+    if (sRfcInterface)
+    {
+        sRfcInterface->rdut_rfcomm(3);
+    }
+    else
+    {
+        bdt_log("interface not loaded");
+    }
+}
+
+void bdt_init(void)
+{
+    bdt_log("INIT BT ");
+    status = sBtInterface->init(&bt_callbacks);
+    if (status == BT_STATUS_SUCCESS) {
+        status = sBtInterface->set_os_callouts(&callouts);
+    }
+    check_return_status(status);
+}
+
+void bdt_enable(void)
+{
+    bdt_log("ENABLE BT");
+    if (bt_enabled) {
+        bdt_log("Bluetooth is already enabled");
+        return;
+    }
+    status = sBtInterface->enable(strict_mode);
+
+    check_return_status(status);
+}
+
+void bdt_disable(void)
+{
+    bdt_log("DISABLE BT");
+    if (!bt_enabled) {
+        bdt_log("Bluetooth is already disabled");
+        return;
+    }
+    status = sBtInterface->disable();
+
+    check_return_status(status);
+}
+void bdt_dut_mode_configure(char *p)
+{
+    int32_t mode = -1;
+
+    bdt_log("BT DUT MODE CONFIGURE");
+    if (!bt_enabled) {
+        bdt_log("Bluetooth must be enabled for test_mode to work.");
+        return;
+    }
+    mode = get_signed_int(&p, mode);
+    if ((mode != 0) && (mode != 1)) {
+        bdt_log("Please specify mode: 1 to enter, 0 to exit");
+        return;
+    }
+    status = sBtInterface->dut_mode_configure(mode);
+
+    check_return_status(status);
+}
+
+#define HCI_LE_RECEIVER_TEST_OPCODE 0x201D
+#define HCI_LE_TRANSMITTER_TEST_OPCODE 0x201E
+#define HCI_LE_END_TEST_OPCODE 0x201F
+
+void bdt_le_test_mode(char *p)
+{
+    int cmd;
+    unsigned char buf[3];
+    int arg1, arg2, arg3;
+
+    bdt_log("BT LE TEST MODE");
+    if (!bt_enabled) {
+        bdt_log("Bluetooth must be enabled for le_test to work.");
+        return;
+    }
+
+    memset(buf, 0, sizeof(buf));
+    cmd = get_int(&p, 0);
+    switch (cmd)
+    {
+        case 0x1: /* RX TEST */
+           arg1 = get_int(&p, -1);
+           if (arg1 < 0) bdt_log("%s Invalid arguments", __FUNCTION__);
+           buf[0] = arg1;
+           status = sBtInterface->le_test_mode(HCI_LE_RECEIVER_TEST_OPCODE, buf, 1);
+           break;
+        case 0x2: /* TX TEST */
+            arg1 = get_int(&p, -1);
+            arg2 = get_int(&p, -1);
+            arg3 = get_int(&p, -1);
+            if ((arg1 < 0) || (arg2 < 0) || (arg3 < 0))
+                bdt_log("%s Invalid arguments", __FUNCTION__);
+            buf[0] = arg1;
+            buf[1] = arg2;
+            buf[2] = arg3;
+            status = sBtInterface->le_test_mode(HCI_LE_TRANSMITTER_TEST_OPCODE, buf, 3);
+           break;
+        case 0x3: /* END TEST */
+            status = sBtInterface->le_test_mode(HCI_LE_END_TEST_OPCODE, buf, 0);
+           break;
+        default:
+            bdt_log("Unsupported command");
+            return;
+            break;
+    }
+    if (status != BT_STATUS_SUCCESS)
+    {
+        bdt_log("%s Test 0x%x Failed with status:0x%x", __FUNCTION__, cmd, status);
+    }
+    return;
+}
+
+void bdt_cleanup(void)
+{
+    bdt_log("CLEANUP");
+    sBtInterface->cleanup();
+}
+
+/*******************************************************************************
+ ** Console commands
+ *******************************************************************************/
+
+static int pos = 0;
+
+void do_help(char *p)
+{
+    int i = 0;
+    char line[128];
+
+    while (console_cmd_list[i].name != NULL)
+    {
+        pos = snprintf(line, sizeof(line), "%s", (char*)console_cmd_list[i].name);
+        bdt_log("%s %s\n", (char*)line, (char*)console_cmd_list[i].help);
+        i++;
+    }
+}
+
+void do_quit(char *p)
+{
+    bdt_shutdown();
+}
+
+/*******************************************************************
+ *
+ *  BT TEST  CONSOLE COMMANDS
+ *
+ *  Parses argument lists and passes to API test function
+ *
+*/
+
+void do_init(char *p)
+{
+    bdt_init();
+}
+
+void do_enable(char *p)
+{
+    bdt_enable();
+}
+
+void do_disable(char *p)
+{
+    bdt_disable();
+}
+void do_dut_mode_configure(char *p)
+{
+    bdt_dut_mode_configure(p);
+}
+
+void do_le_test_mode(char *p)
+{
+    bdt_le_test_mode(p);
+}
+
+void do_cleanup(char *p)
+{
+    bdt_cleanup();
+}
+
+/********* Rfcomm Test toot ***************/
+void do_rfcomm(char *p)
+{
+    bdt_rfcomm();
+}
+
+
+/**********************************************
+  Rfcomm connection to remote device
+************************************************/
+void do_rfc_con( char *p)
+{
+    char            buf[64];
+    tRFC            conn_param;
+
+    bdt_log("bdt do_rfc_con");
+    memset(buf, 0, 64);
+    /*Enter BD address */
+    get_str(&p, buf);
+    str2bd(buf, &conn_param.data.conn.bdadd);
+    memset(buf ,0 , 64);
+    get_str(&p, buf);
+    conn_param.data.conn.scn = atoi(buf);
+    bdt_log("SCN =%d",conn_param.data.conn.scn);
+    /* Connection */
+    conn_param.param = RFC_TEST_CLIENT;
+    sRfcInterface = (btrfcomm_interface_t *)sBtInterface->get_testapp_interface(TEST_APP_RFCOMM);
+    if (sRfcInterface)
+    {
+        sRfcInterface->rdut_rfcomm_test_interface(&conn_param);
+    }
+    else
+    {
+        bdt_log("interface not loaded");
+    }
+}
+
+
+/* For PTS test case  BV21 and BV22 */
+
+void do_rfc_con_for_test_msc_data(char *p)
+{
+    char            buf[64];
+    tRFC            conn_param;
+
+    bdt_log("bdt do_rfc_con_for_test_msc_data");
+    memset(buf, 0, 64);
+    /*Enter BD address */
+    get_str(&p, buf);
+    str2bd(buf, &conn_param.data.conn.bdadd);
+    memset(buf ,0 , 64);
+    get_str(&p, buf);
+    conn_param.data.conn.scn = atoi(buf);
+    bdt_log("SCN =%d",conn_param.data.conn.scn);
+    /* Connection */
+    conn_param.param = RFC_TEST_CLIENT_TEST_MSC_DATA;
+    sRfcInterface = (btrfcomm_interface_t *)sBtInterface->
+                         get_testapp_interface(TEST_APP_RFCOMM);
+    if (sRfcInterface)
+    {
+        sRfcInterface->rdut_rfcomm_test_interface(&conn_param);
+    }
+    else
+    {
+        bdt_log("interface not loaded");
+    }
+}
+
+
+
+/* Role Switch */
+void do_role_switch(char *p)
+{
+    char   buf[64];
+    tRFC conn_param ;
+
+    bdt_log("bdt do_role_switch");
+    memset(buf ,0 , 64);
+    /* Bluetooth Device address */
+    get_str(&p, buf);
+    str2bd(buf, &conn_param.data.role_switch.bdadd);
+    memset(buf ,0 , 64);
+    get_str(&p, buf);
+    conn_param.data.role_switch.role = atoi(buf);
+    /* Role Switch */
+    conn_param.param = RFC_TEST_ROLE_SWITCH; //role switch
+    sRfcInterface = (btrfcomm_interface_t *)sBtInterface->get_testapp_interface(TEST_APP_RFCOMM);
+    if (sRfcInterface)
+    {
+        sRfcInterface->rdut_rfcomm_test_interface(&conn_param);
+    }
+    else
+    {
+        bdt_log("interface not loaded");
+    }
+}
+
+void do_rfc_rls (char *p)
+{
+    tRFC  conn_param;
+
+    bdt_log("bdt rfc_rls");
+    conn_param.param = RFC_TEST_FRAME_ERROR;
+    sRfcInterface = (btrfcomm_interface_t *)sBtInterface->get_testapp_interface(TEST_APP_RFCOMM);
+    if (sRfcInterface)
+    {
+        sRfcInterface->rdut_rfcomm_test_interface(&conn_param);
+    }
+    else
+    {
+        bdt_log("interface not loaded");
+    }
+
+}
+
+void do_rfc_send_data (char *p)
+{
+    tRFC  conn_param;
+
+    bdt_log("bdt rfc_send_data");
+    conn_param.param = RFC_TEST_WRITE_DATA;
+    sRfcInterface = (btrfcomm_interface_t *)sBtInterface->get_testapp_interface(TEST_APP_RFCOMM);
+    if (sRfcInterface)
+    {
+        sRfcInterface->rdut_rfcomm_test_interface(&conn_param);
+    }
+    else
+    {
+        bdt_log("interface not loaded");
+    }
+
+}
+
+
+void do_rfcomm_server(char *p)
+{
+    bdt_rfcomm_server();
+}
+
+void do_rfcomm_disc_frm_server(char *p)
+{
+   bdt_rfcomm_disc_from_server();
+}
+/*******************************************************************
+ *
+ *  CONSOLE COMMAND TABLE
+ *
+*/
+
+const t_cmd console_cmd_list[] =
+{
+    /*
+     * INTERNAL
+     */
+
+    { "help", do_help, "lists all available console commands", 0 },
+    { "quit", do_quit, "", 0},
+
+    /*
+     * API CONSOLE COMMANDS
+     */
+
+     /* Init and Cleanup shall be called automatically */
+    { "enable", do_enable, ":: enables bluetooth", 0 },
+    { "disable", do_disable, ":: disables bluetooth", 0 },
+    { "dut_mode_configure", do_dut_mode_configure, ":: DUT mode - 1 to enter,0 to exit", 0 },
+    { "le_test_mode", do_le_test_mode, ":: LE Test Mode - RxTest - 1 <rx_freq>, \n\t \
+                      TxTest - 2 <tx_freq> <test_data_len> <payload_pattern>, \n\t \
+                      End Test - 3 <no_args>", 0 },
+    /* add here */
+    { "rfcomm", do_rfcomm, "rfcomm test", 0},
+    { "server_rfcomm", do_rfcomm_server ,"rfcomm server test", 0},
+    { "dis_client", do_rfcomm_disc_frm_server, "disc from Server", 0},
+    { "rfc_con", do_rfc_con, "rfc_con", 0 },
+    { "rfc_msccon", do_rfc_con_for_test_msc_data, "rfc_msccon", 0 },
+    { "rfc_rls", do_rfc_rls, "rls",     0 },
+    { "rfc_senddata", do_rfc_send_data, "rfc_senddata",     0 },
+    { "role_sw", do_role_switch, "role_sw", 0},
+    /* last entry */
+    {NULL, NULL, "", 0},
+};
+
+/*
+ * Main console command handler
+*/
+
+static void process_cmd(char *p, unsigned char is_job)
+{
+    char cmd[128];
+    int i = 0;
+    char *p_saved = p;
+
+    get_str(&p, cmd);
+
+    /* table commands */
+    while (console_cmd_list[i].name != NULL)
+    {
+        if (is_cmd(console_cmd_list[i].name))
+        {
+            if (!is_job && console_cmd_list[i].is_job)
+                create_cmdjob(p_saved);
+            else
+            {
+                console_cmd_list[i].handler(p);
+            }
+            return;
+        }
+        i++;
+    }
+    bdt_log("%s : unknown command\n", p_saved);
+    do_help(NULL);
+}
+
+int main (int argc, char * argv[])
+{
+
+    config_permissions();
+    bdt_log("\n:::::::::::::::::::::::::::::::::::::::::::::::::::");
+    bdt_log(":: Bluedroid test app starting");
+
+    if ( HAL_load() < 0 ) {
+        perror("HAL failed to initialize, exit\n");
+        unlink(PID_FILE);
+        exit(0);
+    }
+
+    setup_test_env();
+
+    /* Automatically perform the init */
+    bdt_init();
+
+    while(!main_done)
+    {
+        char line[128];
+
+        /* command prompt */
+        printf( ">" );
+        fflush(stdout);
+
+        fgets (line, 128, stdin);
+
+        if (line[0]!= '\0')
+        {
+            /* remove linefeed */
+            line[strlen(line)-1] = 0;
+
+            process_cmd(line, 0);
+            memset(line, '\0', 128);
+        }
+    }
+
+    /* FIXME: Commenting this out as for some reason, the application does not exit otherwise*/
+    //bdt_cleanup();
+//cleanup:
+    HAL_unload();
+
+    bdt_log(":: Bluedroid test app terminating");
+
+    return 0;
+}
diff --git a/udrv/ulinux/uipc.c b/udrv/ulinux/uipc.c
index abb747d..c5cf905 100644
--- a/udrv/ulinux/uipc.c
+++ b/udrv/ulinux/uipc.c
@@ -67,6 +67,9 @@
 
 #define UIPC_FLUSH_BUFFER_SIZE 1024
 
+#define CHAN_CREATE_WAIT_TIME_MS 30
+#define CHAN_CREATE_RETRY_COUNT 10
+
 /*****************************************************************************
 **  Local type definitions
 ******************************************************************************/
@@ -143,6 +146,7 @@
 
 static inline int create_server_socket(const char* name)
 {
+    int ret;
     int s = socket(AF_LOCAL, SOCK_STREAM, 0);
     if (s < 0)
         return -1;
@@ -151,9 +155,10 @@
 
     if(osi_socket_local_server_bind(s, name, ANDROID_SOCKET_NAMESPACE_ABSTRACT) < 0)
     {
+        ret = (errno == EADDRINUSE ? -EADDRINUSE : -1);
         BTIF_TRACE_EVENT("socket failed to create (%s)", strerror(errno));
         close(s);
-        return -1;
+        return ret;
     }
 
     if(listen(s, 5) < 0)
@@ -350,6 +355,7 @@
 static int uipc_setup_server_locked(tUIPC_CH_ID ch_id, char *name, tUIPC_RCV_CBACK *cback)
 {
     int fd;
+    int i;
 
     BTIF_TRACE_EVENT("SETUP CHANNEL SERVER %d", ch_id);
 
@@ -358,7 +364,19 @@
 
     UIPC_LOCK();
 
-    fd = create_server_socket(name);
+    for (i = 0; i < CHAN_CREATE_RETRY_COUNT; i++)
+    {
+        fd = create_server_socket(name);
+        if (fd == -EADDRINUSE)
+        {
+            BTIF_TRACE_ERROR("Address already in use, retry: %d", i);
+            usleep(CHAN_CREATE_WAIT_TIME_MS * 1000);
+        }
+        else
+        {
+            break;
+        }
+    }
 
     if (fd < 0)
     {
@@ -436,7 +454,6 @@
         case UIPC_CH_ID_AV_CTRL:
             uipc_flush_ch_locked(UIPC_CH_ID_AV_CTRL);
             break;
-
         case UIPC_CH_ID_AV_AUDIO:
             uipc_flush_ch_locked(UIPC_CH_ID_AV_AUDIO);
             break;
@@ -644,6 +661,7 @@
         case UIPC_CH_ID_AV_AUDIO:
             uipc_setup_server_locked(ch_id, A2DP_DATA_PATH, p_cback);
             break;
+
     }
 
     UIPC_UNLOCK();
diff --git a/utils/Android.mk b/utils/Android.mk
index e28d5fa..4a83236 100644
--- a/utils/Android.mk
+++ b/utils/Android.mk
@@ -8,11 +8,16 @@
 	$(LOCAL_PATH)/include \
 	$(LOCAL_PATH)/../btcore/include \
 	$(LOCAL_PATH)/../stack/include \
+	$(LOCAL_PATH)/../gki/common \
+	$(LOCAL_PATH)/../include \
 	$(LOCAL_PATH)/../ \
 	$(bluetooth_C_INCLUDES)
 
 LOCAL_SRC_FILES := \
-	./src/bt_utils.c
+        ./src/bt_utils.c
+
+LOCAL_STATIC_LIBRARIES := \
+        libosi
 
 LOCAL_MODULE := libbt-utils
 LOCAL_MODULE_TAGS := optional
diff --git a/utils/include/bt_utils.h b/utils/include/bt_utils.h
index fa397f9..960a283 100644
--- a/utils/include/bt_utils.h
+++ b/utils/include/bt_utils.h
@@ -21,6 +21,7 @@
 
 static const char BT_UTILS_MODULE[] = "bt_utils_module";
 
+#include <stdbool.h>
 /*******************************************************************************
 **  Type definitions
 ********************************************************************************/
@@ -36,11 +37,46 @@
     TASK_HIGH_MAX
 } tHIGH_PRIORITY_TASK;
 
+/* Run-time configuration file to store AVRCP version info*/
+#ifndef AVRC_PEER_VERSION_CONF_FILE
+#define AVRC_PEER_VERSION_CONF_FILE "/data/misc/bluedroid/avrc_peer_entries.conf"
+#endif
+
 /*******************************************************************************
 **  Functions
 ********************************************************************************/
 
+typedef enum {
+    METHOD_BD = 0,
+    METHOD_NAME
+} tBLACKLIST_METHOD;
+
+typedef enum {
+    BT_SOC_DEFAULT = 0,
+    BT_SOC_SMD = BT_SOC_DEFAULT,
+    BT_SOC_AR3K,
+    BT_SOC_ROME,
+    BT_SOC_CHEROKEE,
+    /* Add chipset type here */
+    BT_SOC_RESERVED
+} bt_soc_type;
+
+#define MAX_NAME_LEN                  (50)
+#define IOT_DEV_BASE_CONF_FILE        "/etc/bluetooth/iot_devlist.conf"
+#define IOT_DEV_CONF_FILE             "/data/misc/bluedroid/iot_devlist.conf"
+#define IOT_DEV_CONF_BKP_FILE         "/data/misc/bluedroid/iot_devlist_bkp.conf"
+#define IOT_ROLE_CHANGE_BLACKLIST     "RoleChangeBlacklistAddr"
+#define IOT_HFP_1_7_BLACKLIST          "Hfp1_7BlacklistAddr"
+#define COD_AUDIO_DEVICE              (0x200400)
 void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task);
 void adjust_priority_a2dp(int start);
+void load_iot_devlist(const char *filename);
+void unload_iot_devlist();
+bool is_device_present(char* header, unsigned char* device_details);
+bool add_iot_device(const char *filename, char* header,
+    unsigned char* device_details, tBLACKLIST_METHOD method_type);
+bool remove_iot_device(const char *filename, char* header,
+    unsigned char* device_details, tBLACKLIST_METHOD method_type);
+bt_soc_type get_soc_type();
 #define UNUSED(x) (void)(x)
 #endif /* BT_UTILS_H */
diff --git a/utils/src/bt_utils.c b/utils/src/bt_utils.c
index 2c3422a..6f0f205 100644
--- a/utils/src/bt_utils.c
+++ b/utils/src/bt_utils.c
@@ -42,10 +42,53 @@
 #include "bt_types.h"
 #include "btcore/include/module.h"
 #include "osi/include/compat.h"
+#include "osi/include/allocator.h"
 #include "osi/include/log.h"
 #include "osi/include/properties.h"
+#include "osi/include/list.h"
+#include <string.h>
 
 /*******************************************************************************
+**  Local type definitions
+*******************************************************************************/
+typedef struct {
+    char header_name[MAX_NAME_LEN];             // name of header in iot_devlist_conf file
+    list_t *devlist;                  // list of BD addresses
+    tBLACKLIST_METHOD method_type;
+} iot_header_node_t;
+
+typedef struct {
+    char dev_bd[3];                  // BD address of blacklisted device
+} iot_devlist_bd_node_t;
+
+typedef struct {
+    char dev_name[MAX_NAME_LEN];              // Name of blacklisted device
+} iot_devlist_name_node_t;
+
+typedef struct {
+    char *header;                   // header name
+    unsigned char *dev_details;              // details of blacklisted device
+    bool device_found;
+} iot_input_param;
+
+typedef struct {
+    bt_soc_type soc_type;
+    char* soc_name;
+} soc_type_node;
+
+static soc_type_node soc_type_entries[] = {
+                           { BT_SOC_SMD , "smd" },
+                           { BT_SOC_AR3K , "ath3k" },
+                           { BT_SOC_ROME , "rome" },
+                           { BT_SOC_CHEROKEE , "cherokee" },
+                           { BT_SOC_RESERVED , "" }
+                                       };
+
+static list_t *iot_header_queue = NULL;
+#define MAX_LINE 2048
+#define MAX_ADDR_STR_LEN 9
+static pthread_mutex_t         iot_mutex_lock;
+/*******************************************************************************
 **  Type definitions for callback functions
 ********************************************************************************/
 static pthread_once_t g_DoSchedulingGroupOnce[TASK_HIGH_MAX];
@@ -53,8 +96,11 @@
 static pthread_mutex_t         gIdxLock;
 static int g_TaskIdx;
 static int g_TaskIDs[TASK_HIGH_MAX];
+static bt_soc_type soc_type;
 #define INVALID_TASK_ID  (-1)
 
+static void init_soc_type();
+
 static future_t *init(void) {
   int i;
   pthread_mutexattr_t lock_attr;
@@ -67,11 +113,14 @@
 
   pthread_mutexattr_init(&lock_attr);
   pthread_mutex_init(&gIdxLock, &lock_attr);
+  pthread_mutex_init(&iot_mutex_lock, NULL);
+  init_soc_type();
   return NULL;
 }
 
 static future_t *clean_up(void) {
   pthread_mutex_destroy(&gIdxLock);
+  pthread_mutex_destroy(&iot_mutex_lock);
   return NULL;
 }
 
@@ -129,7 +178,7 @@
     rc = -1;
 #else  // !defined(OS_GENERIC)
     pthread_once(&g_DoSchedulingGroupOnce[g_TaskIdx], check_do_scheduling_group);
-    if (g_DoSchedulingGroup[g_TaskIdx]) {
+    if (g_TaskIdx < TASK_HIGH_MAX && g_DoSchedulingGroup[g_TaskIdx]) {
         // set_sched_policy does not support tid == 0
         rc = set_sched_policy(tid, SP_AUDIO_SYS);
     }
@@ -181,3 +230,900 @@
         }
     }
 }
+
+/*****************************************************************************
+**
+** Function        check_bd_cb
+**
+** Description     Compares the BD address.
+**
+** Returns         returns true if the BD address matches otherwise false
+**
+*******************************************************************************/
+static bool check_bd_cb(void* node, void* cb_data)
+{
+    iot_devlist_bd_node_t *bd_node = (iot_devlist_bd_node_t*)node;
+    iot_input_param *input_param = (iot_input_param*)cb_data;
+
+    if (input_param->device_found == true)
+        return true;
+
+    if ((bd_node->dev_bd[0] == input_param->dev_details[0]) &&
+        (bd_node->dev_bd[1] == input_param->dev_details[1]) &&
+        (bd_node->dev_bd[2] == input_param->dev_details[2])) {
+        input_param->device_found = true;
+        return true;
+    }
+    return false;
+}
+
+/*****************************************************************************
+**
+** Function        check_name_cb
+**
+** Description     Compares the Device name.
+**
+** Returns         returns true if the name matches otherwise false
+**
+*******************************************************************************/
+static bool check_name_cb(void* node, void* cb_data)
+{
+    iot_devlist_name_node_t *name_node = (iot_devlist_name_node_t*)node;
+    iot_input_param *input_param = (iot_input_param*)cb_data;
+
+    if (input_param->device_found == true)
+        return true;
+
+    if (!strncmp(name_node->dev_name, (const char*)input_param->dev_details,
+                                                strlen((char *)input_param->dev_details))) {
+        input_param->device_found = true;
+        return true;
+    }
+    return false;
+}
+
+/*****************************************************************************
+**
+** Function        check_header_cb
+**
+** Description     Iterates through the each entry in the header list and
+**                 calls the callback associated to each entry.
+**
+** Returns         boolean
+**
+*******************************************************************************/
+static bool check_header_cb(void* node, void* cb_data)
+{
+    iot_header_node_t *header_node = (iot_header_node_t*)node;
+    iot_input_param *input_param = (iot_input_param*)cb_data;
+    if (!strcmp(header_node->header_name, input_param->header)) {
+        if(header_node->devlist) {
+            if (header_node->method_type == METHOD_BD)
+                list_foreach_ext(header_node->devlist, check_bd_cb, cb_data);
+            else if (header_node->method_type == METHOD_NAME)
+                list_foreach_ext(header_node->devlist, check_name_cb, cb_data);
+        }
+    }
+    return true;
+}
+
+/*****************************************************************************
+**
+** Function        is_device_present
+**
+** Description     Checks if the device is already present in the blacklisted
+**                 device list or not.The input can be address based or name
+**                 based.
+**
+** Returns         true incase device is present false otherwise.
+**
+*******************************************************************************/
+bool is_device_present(char* header, unsigned char* device_details)
+{
+    iot_input_param input_param;
+    input_param.dev_details = device_details;
+    input_param.header = header;
+    input_param.device_found = false;
+
+    pthread_mutex_lock(&iot_mutex_lock);
+    if (!iot_header_queue) {
+        pthread_mutex_unlock(&iot_mutex_lock);
+        return false;
+    }
+    list_foreach_ext(iot_header_queue, check_header_cb, &input_param);
+    pthread_mutex_unlock(&iot_mutex_lock);
+
+    if (input_param.device_found)
+        return true;
+    else
+        return false;
+}
+
+/*****************************************************************************
+**
+** Function        parse_bd
+**
+** Description     It will read 3 bytes and copy them into node. It also
+**                 increments header pointer.
+**
+** Returns         void.
+**
+*******************************************************************************/
+static void parse_bd(char **start_ptr, iot_devlist_bd_node_t *bd)
+{
+    char *p_end;
+    bd->dev_bd[0] = (unsigned char)strtol(*start_ptr, &p_end, 16);
+    (*start_ptr) = p_end + 1;
+    bd->dev_bd[1] = (unsigned char)strtol(*start_ptr, &p_end, 16);
+    (*start_ptr) = p_end + 1;
+    bd->dev_bd[2] = (unsigned char)strtol(*start_ptr, &p_end, 16);
+    (*start_ptr) = p_end;
+}
+
+/*****************************************************************************
+**
+** Function        parse_name
+**
+** Description     It will read name and copy them into node. It also
+**                 increments header pointer.
+**
+** Returns         void.
+**
+*******************************************************************************/
+static void parse_name(char **start_ptr, iot_devlist_name_node_t *name)
+{
+    char *split = strchr(*start_ptr, ','); // split point to first occurrence of ,
+    int len = 0;
+    if (split == NULL) {
+        // check once for end of line, for the last name in list
+        split = strchr(*start_ptr, '\n');
+        if (split == NULL)
+            return;
+    }
+    len = (((split - (*start_ptr)) >= MAX_NAME_LEN) ? MAX_NAME_LEN - 1 :
+                                            (split - (*start_ptr)));
+    memcpy(name->dev_name, *start_ptr, len);
+    name->dev_name[len] = '\0';
+    *start_ptr = split;
+}
+
+/*****************************************************************************
+**
+** Function        is_device_node_exist
+**
+** Description     Checks if the device node is already present in the queue
+**                 or not.The input can be address based or name  based.
+**
+** Returns         true if the entry found else false.
+**
+*******************************************************************************/
+static bool is_device_node_exist(iot_header_node_t *header_entry, char* device_details,
+                    tBLACKLIST_METHOD method_type)
+{
+    if(!header_entry || !header_entry->devlist)
+        return false;
+
+    for (const list_node_t *device_node = list_begin(header_entry->devlist);
+            device_node != list_end(header_entry->devlist);
+            device_node = list_next(device_node)) {
+        if(method_type == METHOD_BD) {
+            iot_devlist_bd_node_t *bd_addr_entry = list_node(device_node);
+            if(!memcmp(device_details, bd_addr_entry->dev_bd, 3)) {
+                return true;
+            }
+        }
+        else if(method_type == METHOD_NAME) {
+            iot_devlist_name_node_t *bd_name_entry = list_node(device_node);
+            if(!strcmp((char *)device_details, bd_name_entry->dev_name)) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+/*****************************************************************************
+**
+** Function        populate_list
+**
+** Description     It goes through the input buffer and add device node to the
+**                 header list if the valid entry is found.It ignores the
+**                 duplicated entries.
+**
+** Returns         void.
+**
+*******************************************************************************/
+static void populate_list(char *header_end, iot_header_node_t *node)
+{
+    if(node->devlist == NULL)
+        node->devlist = list_new(osi_free);
+    while(header_end && (*header_end != '\n')&&(*header_end != '\0')) // till end of line reached
+    {
+        // read from line buffer and copy to list
+        if (node->method_type == METHOD_BD) {
+            iot_devlist_bd_node_t *bd = (iot_devlist_bd_node_t *)osi_malloc(sizeof(iot_devlist_bd_node_t));
+            if(bd == NULL) {
+                ALOGE(" Unable to allocate memory for addr entry");
+                return;
+            }
+            header_end++;
+            parse_bd(&header_end, bd);
+            if(is_device_node_exist(node, (char *) bd, node->method_type)) {
+                osi_free(bd);
+            }
+            else {
+                list_append(node->devlist, bd);
+            }
+        }
+        else if (node->method_type == METHOD_NAME) {
+            iot_devlist_name_node_t *name = (iot_devlist_name_node_t *)osi_malloc(sizeof(iot_devlist_name_node_t));
+            if(name == NULL) {
+                ALOGE(" Unable to allocate memory for name entry");
+                return;
+            }
+            header_end++;
+            parse_name(&header_end, name);
+            if(is_device_node_exist(node, (char *)name, node->method_type)) {
+                osi_free(name);
+            }
+            else {
+                list_append(node->devlist, name);
+            }
+        }
+    }
+}
+
+/*****************************************************************************
+**
+** Function        create_header_node
+**
+** Description     This function is used to create the header node.
+**
+** Returns         valid pointer incase the node is created otherwise NULL.
+**
+*******************************************************************************/
+static iot_header_node_t *create_header_node(char* name, unsigned int len,
+                        tBLACKLIST_METHOD method_type)
+{
+    iot_header_node_t *node = NULL;
+    if(len >= MAX_NAME_LEN) {
+        return NULL;
+    }
+    node =(iot_header_node_t *) osi_malloc(sizeof(iot_header_node_t));
+    if (node == NULL) {
+       ALOGE(" Not enough memory to create the header node");
+       return NULL;
+    }
+    memcpy(node->header_name, name, len);
+    node->header_name[len] = '\0';  // header copied
+    node->method_type = method_type;
+    node->devlist = NULL;
+    return node;
+}
+
+/*****************************************************************************
+**
+** Function        get_existing_header_node
+**
+** Description     This function is used to get exisiting header node if present.
+**
+** Returns         valid pointer incase the node is already prsent otherwise NULL.
+**
+*******************************************************************************/
+static iot_header_node_t *get_existing_header_node(char* name, unsigned int len)
+{
+    for (const list_node_t *node = list_begin(iot_header_queue);
+           node != list_end(iot_header_queue); node = list_next(node)) {
+        iot_header_node_t *entry = list_node(node);
+        if (!strncmp(entry->header_name, name, len)) {
+            return entry;
+        }
+    }
+    return NULL;
+}
+
+/*****************************************************************************
+**
+** Function        populate_header
+**
+** Description     It goes through the input buffer and add header node to the
+**                 main queue if the valid entry is found.It ignores the
+**                 duplicated entries.
+**
+** Returns         void.
+**
+*******************************************************************************/
+static void populate_header(char* line_start, char *header_end)
+{
+    tBLACKLIST_METHOD method_type;
+    iot_header_node_t *node = NULL;
+
+    if (*(header_end + 3) == ':')
+        method_type = METHOD_BD;
+    else
+        method_type = METHOD_NAME;
+
+    if (!iot_header_queue) {
+        iot_header_queue = list_new(osi_free);
+        if (iot_header_queue == NULL) {
+            ALOGE(" Not enough memory  to create the queue");
+            return;
+        }
+    }
+
+    if( (node = get_existing_header_node(line_start,  header_end - line_start)) == NULL) {
+        node = create_header_node(line_start, header_end - line_start, method_type);
+        if(node)
+            list_append(iot_header_queue, node);
+    }
+    if(node)
+        populate_list(header_end, node);
+}
+
+/*****************************************************************************
+**
+** Function        free_header_list
+**
+** Description     This function is used to free all entries under blacklist
+**                 queue.
+**
+** Returns         boolean
+**
+*******************************************************************************/
+static bool free_header_list(void* node, void *context)
+{
+    iot_header_node_t *header_node = (iot_header_node_t*)node;
+    list_free(header_node->devlist);
+    return true;
+}
+
+/*****************************************************************************
+**
+** Function        unload_iot_devlist
+**
+** Description     This function is used to free the IOT blacklist queue.
+**
+** Returns         void
+**
+*******************************************************************************/
+void unload_iot_devlist()
+{
+    pthread_mutex_lock(&iot_mutex_lock);
+    if (!iot_header_queue) {
+        ALOGV(" Blacklist queue is not initialized ");
+        pthread_mutex_unlock(&iot_mutex_lock);
+        return;
+    }
+    list_foreach(iot_header_queue, free_header_list, NULL);
+    list_free(iot_header_queue);
+    iot_header_queue = NULL;
+    pthread_mutex_unlock(&iot_mutex_lock);
+}
+
+/*****************************************************************************
+**
+** Function        copy_file
+**
+** Description     This function is used to copy one file to other.
+**
+** Returns         true incase copy is successful otherwise false.
+**
+*******************************************************************************/
+static bool copy_file(const char *src, const char *dst)
+{
+    FILE *src_fp = NULL, *dst_fp = NULL;
+    int ch;
+
+    if( !src || !dst)  {
+        return false;
+    }
+    src_fp = fopen(src, "rt");
+    if(src_fp)
+        dst_fp = fopen(dst, "wt");
+    if(src_fp && dst_fp) {
+        while( ( ch = fgetc(src_fp) ) != EOF ) {
+            fputc(ch, dst_fp);
+        }
+        fclose(dst_fp);
+        fclose(src_fp);
+        return true;
+    }
+    else {
+        if(src_fp)
+            fclose(src_fp);
+        if(dst_fp)
+            fclose(dst_fp);
+        return false;
+    }
+}
+
+/*****************************************************************************
+**
+** Function        dump_all_iot_devices
+**
+** Description     This function is used to print all blacklisted devices
+**                 which are loaded from iot_devlist.conf file..
+**
+** Returns         void.
+**
+*******************************************************************************/
+static void dump_all_iot_devices(void)
+{
+    tBLACKLIST_METHOD method_type;
+
+    if(!iot_header_queue)
+        return;
+
+    for (const list_node_t *header_node = list_begin(iot_header_queue);
+           header_node != list_end(iot_header_queue);
+           header_node = list_next(header_node)) {
+        iot_header_node_t *header_entry = list_node(header_node);
+        method_type = header_entry->method_type;
+
+        if(!header_entry->devlist)
+            continue;
+
+        ALOGW(" ########### Blacklisted Device summary ##############");
+        for (const list_node_t *device_node = list_begin(header_entry->devlist);
+                device_node != list_end(header_entry->devlist);
+                device_node = list_next(device_node)) {
+            if(method_type == METHOD_BD) {
+                iot_devlist_bd_node_t *bd_addr_entry = list_node(device_node);
+                ALOGW(" Device  %02X:%02X:%02X Blacklisted under %s",
+                    bd_addr_entry->dev_bd[0], bd_addr_entry->dev_bd[1],
+                    bd_addr_entry->dev_bd[2], header_entry->header_name);
+            }
+            else if(method_type == METHOD_NAME) {
+                iot_devlist_name_node_t *bd_name_entry = list_node(device_node);
+                ALOGW(" Device %s Blacklisted under %s", bd_name_entry->dev_name,
+                    header_entry->header_name);
+            }
+        }
+    }
+}
+
+/*****************************************************************************
+**
+** Function        load_iot_devlist_from_file
+**
+** Description     This function is used to initialize the queue and load the
+**                 load the devices from file.
+**
+** Returns         void.
+**
+*******************************************************************************/
+void load_iot_devlist_from_file(const char *filename)
+{
+    if (!filename) {
+        ALOGE(" Invalid IOT blacklist filename");
+        return;
+    }
+    char line_start[MAX_LINE];
+    int line_number = 0;
+    char *header_end = NULL;
+    FILE *iot_devlist_fp = fopen(filename, "rt");
+    if (iot_devlist_fp == NULL) {
+        if(!strcmp(filename, IOT_DEV_CONF_FILE))  {
+            //load it from system partition
+            if(copy_file(IOT_DEV_BASE_CONF_FILE, IOT_DEV_CONF_FILE) == false) {
+                ALOGE(" Can't copy it from Base file %s", IOT_DEV_BASE_CONF_FILE);
+                return;
+            }
+            else {
+                if((iot_devlist_fp = fopen(filename, "rt")) == NULL)
+                    return;
+            }
+        }
+        else {
+            ALOGE(" File %s does not exist ",filename);
+            return;
+        }
+    }
+    while(fgets(line_start, MAX_LINE, iot_devlist_fp))  {
+        line_number++;
+        if((*line_start == '\n') ||(*line_start == '#')) {
+            ALOGV("line %d is empty",line_number);
+            continue;
+        }
+        header_end = strchr(line_start, '=');
+        if (header_end == NULL) {
+            ALOGV(" NOT A valid line %d", line_number);
+            continue;
+        }
+        populate_header(line_start, header_end);
+    }
+    dump_all_iot_devices();
+    fclose(iot_devlist_fp);
+}
+
+/*****************************************************************************
+**
+** Function        load_iot_devlist
+**
+** Description     This function is used to initialize the queue.
+**
+** Returns         void.
+**
+*******************************************************************************/
+void load_iot_devlist(const char *filename)
+{
+    pthread_mutex_lock(&iot_mutex_lock);
+    load_iot_devlist_from_file(filename);
+    pthread_mutex_unlock(&iot_mutex_lock);
+}
+
+/*****************************************************************************
+**
+** Function        add_iot_device
+**
+** Description     This function is used to add the device to the blacklist file
+**                 as well as queue.
+**
+** Returns         true incase the device is blacklisted otherwise fasle.
+**
+*******************************************************************************/
+bool add_iot_device(const char *filename, char* header,
+    unsigned char* device_details, tBLACKLIST_METHOD method_type)
+{
+    char line_start[MAX_LINE];
+    FILE *iot_devlist_fp;
+    char *header_end = NULL;
+    int index = 0, i, len = 0;
+
+    if((header == NULL) || (device_details == NULL)) {
+        ALOGE("Error adding device to the list: Invalid input data");
+        return false;
+    }
+    if (is_device_present (header , device_details)) {
+        ALOGW("Device already present in the blacklist");
+        return true;
+    }
+
+    pthread_mutex_lock(&iot_mutex_lock);
+    iot_devlist_fp = fopen(filename, "a");
+
+    if (iot_devlist_fp == NULL) {
+        ALOGE(" File %s does not exist ", filename);
+        pthread_mutex_unlock(&iot_mutex_lock);
+        return false;
+    }
+    /* first copy the header */
+    len = strlcpy(&line_start[index], header, strlen(header)+ 1);
+    index += len;
+
+    line_start[index++] = '=';
+    /* then copy the device addr/device name */
+    if(method_type == METHOD_BD) {
+        /* for addr take first 3 bytes */
+        for(i = 0; i < 3; i++) {
+            if(i < 2) {
+                len = snprintf(&line_start[index], MAX_LINE - index, "%02X:",
+                                                    *(device_details + i));
+            }
+            else {
+                len = snprintf(&line_start[index], MAX_LINE - index, "%02X",
+                                            *(device_details + i));
+            }
+            index += len;
+        }
+    }
+    else if(method_type == METHOD_NAME) {
+        len = strlcpy(&line_start[index], (const char*) device_details,
+                        strlen((const char*)device_details) + 1);
+        index += len;
+    }
+    /* append the new line characer at the end */
+    line_start[index++] = '\n';
+    line_start[index++] = '\0';
+
+    header_end = strchr(line_start,'=');
+    if(header_end) {
+        populate_header(line_start, header_end);
+    }
+    if(fputs(line_start, iot_devlist_fp)) {
+        fclose(iot_devlist_fp);
+        pthread_mutex_unlock(&iot_mutex_lock);
+        return true;
+    }
+    else {
+        fclose(iot_devlist_fp);
+        pthread_mutex_unlock(&iot_mutex_lock);
+        return false;
+    }
+}
+
+/*****************************************************************************
+**
+** Function        form_bd_addr
+**
+** Description     Adds the colon after 2 bytes to form valid BD address to
+**                 compare the entry prsent in file.
+**
+** Returns         void
+**
+*******************************************************************************/
+static void form_bd_addr(char *addr, char *new_addr, int max_len)
+{
+    int i = 0, index = 0, len =0;
+    /* for addr take first 3 bytes */
+    for(i = 0; i < 3; i++) {
+        if(i < 2) {
+            len = snprintf(&new_addr[index], max_len - index, "%02X:",
+                    *(addr + i));
+        }
+        else {
+            len = snprintf(&new_addr[index], max_len - index, "%02X",
+                    *(addr + i));
+        }
+        index += len;
+    }
+    new_addr[max_len - 1]= '\0';
+}
+
+/*****************************************************************************
+**
+** Function        remove_iot_device_from_queue
+**
+** Description     This function is used remove the entry from internal queue.
+**
+** Returns         true if the entry removed from queue else false.
+**
+*******************************************************************************/
+bool remove_iot_device_from_queue(unsigned char* device_details, char* header,
+        tBLACKLIST_METHOD method_type)
+{
+    if(!iot_header_queue)
+        return false;
+    for (const list_node_t *header_node = list_begin(iot_header_queue);
+           header_node != list_end(iot_header_queue);
+           header_node = list_next(header_node)) {
+        iot_header_node_t *header_entry = list_node(header_node);
+
+        if(!header_entry->devlist)
+            continue;
+
+        if((!strcmp(header, header_entry->header_name)) &&
+             method_type == header_entry->method_type) {
+
+            for (const list_node_t *device_node = list_begin(header_entry->devlist);
+                    device_node != list_end(header_entry->devlist);
+                    device_node = list_next(device_node)) {
+                if(method_type == METHOD_BD) {
+                    iot_devlist_bd_node_t *bd_addr_entry = list_node(device_node);
+                    if(!memcmp(device_details, bd_addr_entry->dev_bd, 3)) {
+                        list_remove(header_entry->devlist, bd_addr_entry);
+                        return true;
+                    }
+                }
+                else if(method_type == METHOD_NAME) {
+                    iot_devlist_name_node_t *bd_name_entry = list_node(device_node);
+                    if(!strcmp((char *)device_details, bd_name_entry->dev_name)) {
+                        list_remove(header_entry->devlist, bd_name_entry);
+                        return true;
+                    }
+                }
+            }
+        }
+    }
+    return false;
+}
+
+/*****************************************************************************
+**
+** Function        edit_line
+**
+** Description     This function is used to remove the device entry from the
+**                 inputted line buffer if the entry present.
+**
+** Returns         true if the entry removed from line else false.
+**
+*******************************************************************************/
+static void edit_line(char *line_start, char *dev_info, int line_len)
+{
+    char *dev_ptr = strstr(line_start, dev_info);
+    char *comma_ptr = NULL;
+    int len_to_copy = 0;
+    if(dev_ptr) {
+        comma_ptr = strchr(dev_ptr, ',');
+        if(comma_ptr) {
+            len_to_copy = line_len - (comma_ptr - line_start + 1);
+        }
+        else {
+            *(dev_ptr - 1) = '\n';
+            *(dev_ptr) = '\0';
+        }
+    }
+    if(len_to_copy) {
+        memmove(dev_ptr, comma_ptr + 1, len_to_copy);
+    }
+}
+
+/*****************************************************************************
+**
+** Function        is_single_entry_line
+**
+** Description     This function is used to check the line consists of single
+**                 input line if the entry present.
+**
+** Returns         true if the single entry present else false.
+**
+*******************************************************************************/
+static bool is_single_entry_line(char *line_start)
+{
+    char *comma_ptr = strchr(line_start, ',');
+    // check the char next to ,
+    if( !comma_ptr || (*(comma_ptr + 1) == '\n')) {
+        return true;
+    }
+    else {
+        return false;
+    }
+}
+
+/*****************************************************************************
+**
+** Function        get_header_from_line
+**
+** Description     This function is used to get the header from line buffer.
+**
+** Returns         true if the header found else false.
+**
+*******************************************************************************/
+bool get_header_from_line(char *line_start, char* header)
+{
+    int i = 0;
+    if(!line_start || !header || !strchr(line_start, '=')) {
+        return false;
+    }
+    while (line_start[i] != '=') {
+        header[i] = line_start[i];
+        i++;
+    }
+    header[i] = '\0';
+    return true;
+}
+
+/*****************************************************************************
+**
+** Function        remove_iot_device
+**
+** Description     This function is used to remove the device from internal
+**                 blacklisted queue as well as black list file.
+**
+** Returns         true if the device is removed else false.
+**
+*******************************************************************************/
+bool remove_iot_device(const char *filename, char* header,
+    unsigned char* device_details, tBLACKLIST_METHOD method_type)
+{
+    char line_start[MAX_LINE];
+    FILE *iot_devlist_fp, *iot_devlist_new_fp;
+    char bd_addr[MAX_ADDR_STR_LEN];
+    char header_name[MAX_NAME_LEN] = { 0 };
+    char *dev = NULL;
+    int len = 0;
+
+    if((header == NULL) || (device_details == NULL)) {
+        ALOGE("Invalid input data to add the device");
+        return false;
+    }
+    if (!is_device_present (header , device_details)) {
+        ALOGW("Device doesn't exist in the list");
+        return false;
+    }
+    pthread_mutex_lock(&iot_mutex_lock);
+    iot_devlist_fp = fopen(filename, "rt");
+
+    if (iot_devlist_fp == NULL) {
+        ALOGE(" File %s does not exist ", filename);
+        pthread_mutex_unlock(&iot_mutex_lock);
+        return false;
+    }
+    iot_devlist_new_fp = fopen(IOT_DEV_CONF_BKP_FILE, "wt");
+
+    if (iot_devlist_new_fp == NULL) {
+        ALOGE(" Unable to create backup file %s", IOT_DEV_CONF_BKP_FILE);
+        fclose(iot_devlist_fp);
+        pthread_mutex_unlock(&iot_mutex_lock);
+        return false;
+    }
+
+    /* then copy the device addr/device name */
+    while (fgets(line_start, sizeof line_start, iot_devlist_fp)) {
+        len = strlen(line_start);
+
+        if (len) {
+            get_header_from_line(line_start, header_name);
+            if(method_type == METHOD_BD) {
+                form_bd_addr((char*)device_details, bd_addr, MAX_ADDR_STR_LEN);
+                dev = bd_addr;
+            }
+            else if(method_type == METHOD_NAME) {
+                dev = (char *) device_details;
+            }
+            // copy as it is if the line consists comments
+            if( (line_start[0] == '#') || (line_start[0] == '/') ||
+                    (line_start[0] == ' ') || (line_start[0] == '\n')) {
+                fputs(line_start, iot_devlist_new_fp);
+            }
+            else if((!strcmp(header_name, header)) && (strstr(line_start, dev))) {
+                if(is_single_entry_line(line_start)) {
+                    if(!remove_iot_device_from_queue(device_details, header, method_type)) {
+                        // if unable to remove from queue put the same line as it is
+                        fputs(line_start, iot_devlist_new_fp);
+                    }
+                    else
+                        ALOGE(" Removed %s device from blacklist file %s", dev, IOT_DEV_CONF_FILE);
+                }
+                else {
+                    // multi line entry
+                    if(remove_iot_device_from_queue(device_details, header, method_type)) {
+                        edit_line(line_start, dev, len + 1);
+                        fputs(line_start, iot_devlist_new_fp);
+                        ALOGE(" Removed %s device from blacklist file %s", dev, IOT_DEV_CONF_FILE);
+                    }
+                    else {
+                        fputs(line_start, iot_devlist_new_fp);
+                    }
+                }
+            }
+            else {
+                fputs(line_start, iot_devlist_new_fp);
+            }
+        }
+    }
+
+    fclose(iot_devlist_fp);
+    fclose(iot_devlist_new_fp);
+    remove(filename);
+    rename(IOT_DEV_CONF_BKP_FILE, filename);
+    pthread_mutex_unlock(&iot_mutex_lock);
+    return true;
+}
+
+/*****************************************************************************
+**
+** Function        init_soc_type
+**
+** Description     Get Bluetooth SoC type from system setting and stores it
+**                 in soc_type.
+**
+** Returns         void.
+**
+*******************************************************************************/
+static void init_soc_type()
+{
+    int ret = 0;
+    char bt_soc_type[PROPERTY_VALUE_MAX];
+
+    ALOGI("init_soc_type");
+
+    soc_type = BT_SOC_DEFAULT;
+    ret = property_get("qcom.bluetooth.soc", bt_soc_type, NULL);
+    if (ret != 0) {
+        int i;
+        ALOGI("qcom.bluetooth.soc set to %s\n", bt_soc_type);
+        for ( i = BT_SOC_AR3K ; i < BT_SOC_RESERVED ; i++ )
+        {
+            char* soc_name = soc_type_entries[i].soc_name;
+            if (!strcmp(bt_soc_type, soc_name)) {
+                soc_type = soc_type_entries[i].soc_type;
+                break;
+            }
+        }
+    }
+}
+
+/*****************************************************************************
+**
+** Function        get_soc_type
+**
+** Description     This function is used to get the Bluetooth SoC type.
+**
+** Returns         bt_soc_type.
+**
+*******************************************************************************/
+bt_soc_type get_soc_type()
+{
+    return soc_type;
+}