Bluetooth-SWB: SWB feature support.

Add support for Super Wide Band which
enhances current voice quality with
HD-Voice.

Change-Id: Iad9c5bd731a682edf7e837b51e243cb153b4398d
diff --git a/packages_apps_bluetooth_ext/jni/Android.bp b/packages_apps_bluetooth_ext/jni/Android.bp
index 66c59ac..cb15b77 100644
--- a/packages_apps_bluetooth_ext/jni/Android.bp
+++ b/packages_apps_bluetooth_ext/jni/Android.bp
@@ -25,6 +25,7 @@
         "com_android_bluetooth_btservice_vendor_socket.cpp",
         "com_android_bluetooth_avrcp_ext.cpp",
         "com_android_bluetooth_ba.cpp",
+        "com_android_bluetooth_hf_vendor.cpp",
     ],
     sanitize: {
         never: true,
diff --git a/packages_apps_bluetooth_ext/jni/com_android_bluetooth_hf_vendor.cpp b/packages_apps_bluetooth_ext/jni/com_android_bluetooth_hf_vendor.cpp
new file mode 100644
index 0000000..f11d4cd
--- /dev/null
+++ b/packages_apps_bluetooth_ext/jni/com_android_bluetooth_hf_vendor.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2019, 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 "BluetoothVendorHfJni"
+
+#include "com_android_bluetooth.h"
+#include <hardware/vendor_hf.h>
+#include "utils/Log.h"
+#include "android_runtime/AndroidRuntime.h"
+
+namespace android {
+static btvendor_hf_interface_t *sBluetoothVendorHfInterface = NULL;
+static jobject mCallbacksObj = NULL;
+static jmethodID method_onSWB;
+
+static jbyteArray marshall_bda(RawAddress* bd_addr) {
+  CallbackEnv sCallbackEnv(__func__);
+  if (!sCallbackEnv.valid()) return nullptr;
+
+  jbyteArray addr = sCallbackEnv->NewByteArray(sizeof(RawAddress));
+  if (!addr) {
+    ALOGE("Fail to new jbyteArray bd addr");
+    return nullptr;
+  }
+  sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(RawAddress),
+                                   (jbyte*)bd_addr);
+  return addr;
+}
+
+static void SwbCallback(uint16_t swb_config, RawAddress* bd_addr) {
+
+    ALOGI("%s", __FUNCTION__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
+    ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
+    if (addr.get() == nullptr) return;
+    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSWB, swb_config,
+                                 addr.get());
+}
+
+static btvendor_hf_callbacks_t sBluetoothVendorHfCallbacks = {
+    sizeof(sBluetoothVendorHfCallbacks),
+    SwbCallback,
+};
+
+static void classInitNative(JNIEnv* env, jclass clazz) {
+
+    method_onSWB = env->GetMethodID(clazz, "onSWB", "(I[B)V");
+    ALOGI("%s: succeeds", __FUNCTION__);
+}
+
+static void initNative(JNIEnv *env, jobject object) {
+    const bt_interface_t* btInf;
+    bt_status_t status;
+
+    if ( (btInf = getBluetoothInterface()) == NULL) {
+        ALOGE("Bluetooth module is not loaded");
+        return;
+    }
+
+    if (mCallbacksObj != NULL) {
+        ALOGW("Cleaning up Bluetooth Vendor callback object");
+        env->DeleteGlobalRef(mCallbacksObj);
+        mCallbacksObj = NULL;
+    }
+
+    if ( (sBluetoothVendorHfInterface = (btvendor_hf_interface_t *)
+          btInf->get_profile_interface(BT_PROFILE_VENDOR_HF_ID)) == NULL) {
+        ALOGE("Failed to get Bluetooth Vendor Interface");
+        return;
+    }
+
+    if ( (status = sBluetoothVendorHfInterface->init(&sBluetoothVendorHfCallbacks))
+                 != BT_STATUS_SUCCESS) {
+        ALOGE("Failed to initialize Bluetooth Vendor, status: %d", status);
+        sBluetoothVendorHfInterface = NULL;
+        return;
+    }
+    mCallbacksObj = env->NewGlobalRef(object);
+}
+
+static void cleanupNative(JNIEnv *env, jobject object) {
+    const bt_interface_t* btInf;
+
+    if ( (btInf = getBluetoothInterface()) == NULL) {
+        ALOGE("Bluetooth module is not loaded");
+        return;
+    }
+
+    if (sBluetoothVendorHfInterface !=NULL) {
+        ALOGW("Cleaning up Bluetooth Vendor Interface...");
+        sBluetoothVendorHfInterface->cleanup();
+        sBluetoothVendorHfInterface = NULL;
+    }
+
+    if (mCallbacksObj != NULL) {
+        ALOGW("Cleaning up Bluetooth Vendor callback object");
+        env->DeleteGlobalRef(mCallbacksObj);
+        mCallbacksObj = NULL;
+    }
+
+}
+
+/* native interface */
+static jint enableSwbNative(JNIEnv* env, jobject thiz, jboolean enable)
+{
+    if (sBluetoothVendorHfInterface == NULL) {
+        ALOGE("No Interface initialized");
+        return JNI_FALSE;
+    }
+
+    int ret = sBluetoothVendorHfInterface->enable_swb(enable);
+
+    if (ret != 0) {
+        ALOGE("%s: Failure", __func__);
+        return JNI_FALSE;
+    } else {
+        ALOGV("%s: Success :%d", __func__, enable);
+    }
+
+    return JNI_TRUE;
+}
+
+static JNINativeMethod sMethods[] = {
+    {"classInitNative", "()V", (void *) classInitNative},
+    {"initNative", "()V", (void *) initNative},
+    {"cleanupNative", "()V", (void *) cleanupNative},
+    { "enableSwbNative", "(Z)I", (void*)enableSwbNative},
+};
+
+int register_com_android_bluetooth_hfp_vendorhfservice(JNIEnv* env)
+{
+    ALOGE("%s:",__FUNCTION__);
+    return jniRegisterNativeMethods(env, "com/android/bluetooth/hfp/vendorhfservice",
+                                    sMethods, NELEM(sMethods));
+}
+
+} /* namespace android */
diff --git a/packages_apps_bluetooth_ext/src/hfp/vendorhfservice.java b/packages_apps_bluetooth_ext/src/hfp/vendorhfservice.java
new file mode 100644
index 0000000..e34999a
--- /dev/null
+++ b/packages_apps_bluetooth_ext/src/hfp/vendorhfservice.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package com.android.bluetooth.hfp;
+
+import android.util.Log;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import com.android.bluetooth.Utils;
+import android.content.Intent;
+import android.content.Context;
+
+final class vendorhfservice {
+    private static final String TAG = "BluetoothVendorHfService";
+    private HeadsetService mService;
+    private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
+
+    static {
+        classInitNative();
+    }
+
+    public vendorhfservice(HeadsetService service) {
+        mService = service;
+    }
+
+    public void init(){
+        initNative();
+    }
+
+    public void cleanup() {
+        cleanupNative();
+    }
+
+    public int enableSwb(boolean enable) {
+        int ret = enableSwbNative(enable);
+        return ret;
+    }
+
+    private BluetoothDevice getDevice(byte[] address) {
+        BluetoothDevice local = mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
+        return local;
+    }
+
+    private void onSWB(int codec, byte[] address) {
+        /*HeadsetStackEvent event =
+                new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_SWB, codec, getDevice(address));
+        sendMessageToService(event);*/
+    }
+
+    private void sendMessageToService(HeadsetStackEvent event) {
+        HeadsetService service = HeadsetService.getHeadsetService();
+        if (service != null) {
+            service.messageFromNative(event);
+        } else {
+            Log.d(TAG,"FATAL: Stack sent event while service is not available: " + event);
+        }
+    }
+
+    private native void initNative();
+    private native static void classInitNative();
+    private native void cleanupNative();
+    private native int enableSwbNative(boolean enable);
+}
diff --git a/system_bt_ext/bta/Android.bp b/system_bt_ext/bta/Android.bp
index 8907668..b87a3ac 100644
--- a/system_bt_ext/bta/Android.bp
+++ b/system_bt_ext/bta/Android.bp
@@ -28,6 +28,7 @@
         "ba/bta_ba.cc",
         "tws_plus/ag/bta_ag_twsp_dev.cc",
         "tws_plus/ag/bta_ag_twsp_sco.cc",
+        "swb/bta_ag_swb.cc"
     ],
     shared_libs: [
         "libcutils",
diff --git a/system_bt_ext/bta/include/bta_ag_swb.h b/system_bt_ext/bta/include/bta_ag_swb.h
new file mode 100644
index 0000000..95b77ca
--- /dev/null
+++ b/system_bt_ext/bta/include/bta_ag_swb.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019, 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 _BTA_AG_SWB_H_
+#define _BTA_AG_SWB_H_
+
+#include "bta_ag_int.h"
+
+#define BTA_AG_SCO_SWB_SETTINGS_Q0_MASK 4
+#define BTA_AG_SCO_SWB_SETTINGS_Q1_MASK 8
+#define BTA_AG_SCO_SWB_SETTINGS_Q2_MASK 16
+#define BTA_AG_SCO_SWB_SETTINGS_Q3_MASK 32
+
+/* Events originated from HF side */
+#define  BTA_AG_AT_QAC_EVT 253
+#define  BTA_AG_AT_QCS_EVT 254
+#define  BTA_AG_SWB_EVT 100 /* SWB SCO codec info */
+#define  BTA_AG_LOCAL_RES_QAC 0x108
+#define  BTA_AG_LOCAL_RES_QCS 0x109
+
+void bta_ag_swb_handle_vs_at_events(tBTA_AG_SCB* p_scb, uint16_t cmd, int16_t int_arg, tBTA_AG_VAL val);
+void bta_ag_send_qac(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
+void bta_ag_send_qcs(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
+tBTA_AG_PEER_CODEC bta_ag_parse_qac(tBTA_AG_SCB* p_scb, char* p_s);
+
+#endif//_BTA_AG_SWB_H_
diff --git a/system_bt_ext/bta/swb/bta_ag_swb.cc b/system_bt_ext/bta/swb/bta_ag_swb.cc
new file mode 100644
index 0000000..ead0572
--- /dev/null
+++ b/system_bt_ext/bta/swb/bta_ag_swb.cc
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2019, 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 <unistd.h>
+#include "bta_ag_swb.h"
+#include "internal_include/bt_trace.h"
+#include "bta_ag_int.h"
+#include "utl.h"
+#include "device/include/interop.h"
+
+#if (SWB_ENABLED == TRUE)
+
+void bta_ag_swb_handle_vs_at_events(tBTA_AG_SCB* p_scb, uint16_t cmd, int16_t int_arg, tBTA_AG_VAL val)
+{
+  APPL_TRACE_DEBUG("%s: p_scb : %x cmd : %d", __func__, p_scb, cmd);
+  switch(cmd) {
+    case BTA_AG_AT_QAC_EVT:
+      p_scb->codec_updated = true;
+      if (p_scb->peer_codecs &  BTA_AG_SCO_SWB_SETTINGS_Q0_MASK) {
+        p_scb->sco_codec = BTA_AG_SCO_SWB_SETTINGS_Q0;
+      } else if (p_scb->peer_codecs & BTA_AG_CODEC_MSBC) {
+        p_scb->sco_codec = UUID_CODEC_MSBC;
+      }
+      bta_ag_send_qac(p_scb, NULL);
+      APPL_TRACE_DEBUG("Received AT+QAC, updating sco codec to SWB: %d", p_scb->sco_codec);
+      val.num = p_scb->peer_codecs;
+      break;
+    case BTA_AG_AT_QCS_EVT: {
+      tBTA_AG_PEER_CODEC codec_type, codec_sent;
+      alarm_cancel(p_scb->codec_negotiation_timer);
+
+      switch (int_arg) {
+        case BTA_AG_SCO_SWB_SETTINGS_Q0:
+          codec_type = BTA_AG_SCO_SWB_SETTINGS_Q0;
+          break;
+        case BTA_AG_SCO_SWB_SETTINGS_Q1:
+          codec_type = BTA_AG_SCO_SWB_SETTINGS_Q1;
+          break;
+        case BTA_AG_SCO_SWB_SETTINGS_Q2:
+          codec_type = BTA_AG_SCO_SWB_SETTINGS_Q2;
+          break;
+        case BTA_AG_SCO_SWB_SETTINGS_Q3:
+          codec_type = BTA_AG_SCO_SWB_SETTINGS_Q3;
+          break;
+        default:
+          APPL_TRACE_ERROR("Unknown codec_uuid %d", int_arg);
+          p_scb->is_swb_codec = false;
+          codec_type = BTA_AG_CODEC_MSBC;
+          p_scb->codec_fallback = true;
+          p_scb->sco_codec = BTA_AG_CODEC_MSBC;
+          break;
+      }
+
+      if (p_scb->codec_fallback)
+        codec_sent = BTA_AG_CODEC_MSBC;
+      else
+        codec_sent = p_scb->sco_codec;
+
+      if (codec_type == codec_sent)
+        bta_ag_sco_codec_nego(p_scb, true);
+      else
+        bta_ag_sco_codec_nego(p_scb, false);
+
+      /* send final codec info to callback */
+      val.num = codec_sent;
+      break;
+    }
+  }
+}
+
+/*******************************************************************************
+ *
+ * Function         bta_ag_send_qcs
+ *
+ * Description      Send +%QCS AT command to peer.
+ *
+ * Returns          void
+ *
+ ******************************************************************************/
+void bta_ag_send_qcs(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
+  uint16_t codec_uuid;
+  if (p_scb->codec_fallback) {
+    if (p_scb->peer_codecs & BTA_AG_CODEC_MSBC) {
+      codec_uuid = UUID_CODEC_MSBC;
+    } else {
+      codec_uuid = UUID_CODEC_CVSD;
+    }
+  } else {
+    codec_uuid = BTA_AG_SCO_SWB_SETTINGS_Q0;
+  }
+
+  /* send +BCS */
+  APPL_TRACE_DEBUG("send +QCS codec is %d", codec_uuid);
+  bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_QCS, NULL, codec_uuid);
+}
+
+/*******************************************************************************
+ *
+ * Function         bta_ag_send_qac
+ *
+ * Description      Send +%QAC AT command to peer.
+ *
+ * Returns          void
+ *
+ ******************************************************************************/
+void bta_ag_send_qac(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
+  /* send +BCS */
+  APPL_TRACE_DEBUG("send +QAC codecs suuported");
+  bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_QAC, "0,4,6,7", 0);
+  if (p_scb->sco_codec == BTA_AG_SCO_SWB_SETTINGS_Q0) {
+      p_scb->is_swb_codec = true;
+  }
+}
+
+tBTA_AG_PEER_CODEC bta_ag_parse_qac(tBTA_AG_SCB* p_scb, char* p_s) {
+  tBTA_AG_PEER_CODEC retval = BTA_AG_CODEC_NONE;
+  uint16_t codec_modes;
+  bool cont = false; /* Continue processing */
+  char* p;
+
+  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;
+
+    codec_modes = utl_str2int(p_s);
+    switch (codec_modes) {
+      case BTA_AG_SCO_SWB_SETTINGS_Q0:
+        retval |= BTA_AG_SCO_SWB_SETTINGS_Q0_MASK;
+        break;
+      case BTA_AG_SCO_SWB_SETTINGS_Q1:
+        retval |= BTA_AG_SCO_SWB_SETTINGS_Q1_MASK;
+        break;
+      case BTA_AG_SCO_SWB_SETTINGS_Q2:
+        retval |= BTA_AG_SCO_SWB_SETTINGS_Q2_MASK;
+        break;
+      case BTA_AG_SCO_SWB_SETTINGS_Q3:
+        retval |= BTA_AG_SCO_SWB_SETTINGS_Q3_MASK;
+        break;
+      default:
+        APPL_TRACE_ERROR("Unknown Codec UUID(%d) received", codec_modes);
+        break;
+    }
+
+    if (cont)
+      p_s = p + 1;
+    else
+      break;
+  }
+
+  return (retval);
+}
+#endif //#if (SWB_ENABLED == TRUE)
+
diff --git a/system_bt_ext/btif/Android.bp b/system_bt_ext/btif/Android.bp
index f6fbc99..59cfaf2 100644
--- a/system_bt_ext/btif/Android.bp
+++ b/system_bt_ext/btif/Android.bp
@@ -34,6 +34,7 @@
         "src/btif_ba.cc",
         "src/btif_twsp_hf.cc",
         "src/btif_iot_config.cc",
+        "src/btif_vendor_hf.cc",
     ],
     shared_libs: [
         "libcutils",
diff --git a/system_bt_ext/btif/src/btif_vendor_hf.cc b/system_bt_ext/btif/src/btif_vendor_hf.cc
new file mode 100644
index 0000000..dc4895e
--- /dev/null
+++ b/system_bt_ext/btif/src/btif_vendor_hf.cc
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2019, 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.
+ ***********************************************************************/
+
+/************************************************************************************
+ *
+ *  Filename:      btif_vendor_hf.cc
+ *
+ *  Description:   Vendor Bluetooth Interface
+ *
+ *
+ ***********************************************************************************/
+
+#define LOG_TAG "bt_btif_vendor_hf"
+
+#include <hardware/vendor_hf.h>
+#include "btif_api.h"
+
+btvendor_hf_callbacks_t *bt_vendor_hf_callbacks = NULL;
+static bool swb_codec_status = false;
+
+/*******************************************************************************
+** VENDOR INTERFACE FUNCTIONS
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** Function         init
+**
+** Description     initializes the vendor interface for HF
+**
+** Returns         bt_status_t
+**
+*******************************************************************************/
+
+static bt_status_t init( btvendor_hf_callbacks_t* callbacks)
+{
+    bt_vendor_hf_callbacks = callbacks;
+    LOG_INFO(LOG_TAG,"init done");
+    return BT_STATUS_SUCCESS;
+}
+
+static void cleanup(void)
+{
+    LOG_INFO(LOG_TAG,"cleanup");
+    if (bt_vendor_hf_callbacks)
+        bt_vendor_hf_callbacks = NULL;
+}
+
+int enable_swb(bool enable) {
+  LOG_INFO(LOG_TAG,"%s: %d", __func__, enable);
+  swb_codec_status = enable;
+  return 0;
+}
+
+static const btvendor_hf_interface_t btvendorhfInterface = {
+    sizeof(btvendorhfInterface),
+    init,
+    cleanup,
+    enable_swb,
+};
+
+void btif_handle_vendor_hf_events(uint16_t event, uint16_t swb_config, RawAddress *bd_addr) {
+    HAL_CBACK(bt_vendor_hf_callbacks, swb_codec_cb, swb_config, bd_addr);
+}
+
+bool get_swb_codec_status() {
+    return swb_codec_status;
+}
+
+/*******************************************************************************
+**
+** Function         btif_vendor_hf_get_interface
+**
+** Description      Get the vendor callback interface
+**
+** Returns          btvendor_hf_interface_t
+**
+*******************************************************************************/
+const btvendor_hf_interface_t *btif_vendor_hf_get_interface()
+{
+    BTIF_TRACE_EVENT("%s", __FUNCTION__);
+    return &btvendorhfInterface;
+}
+
diff --git a/vhal/include/hardware/vendor_hf.h b/vhal/include/hardware/vendor_hf.h
new file mode 100644
index 0000000..6399de6
--- /dev/null
+++ b/vhal/include/hardware/vendor_hf.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019, 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 ANDROID_INCLUDE_BT_HF_VENDOR_H
+#define ANDROID_INCLUDE_BT_HF_VENDOR_H
+
+#include <hardware/bluetooth.h>
+
+__BEGIN_DECLS
+
+#define BT_PROFILE_VENDOR_HF_ID "vendorhfservice"
+
+void btif_handle_vendor_hf_events(uint16_t event, uint16_t swb_config, RawAddress *bd_addr);
+
+/* SWB callback events */
+typedef void (* bt_swb_update_callback)(uint16_t swb_codec_config, RawAddress *bd_addr);
+
+/** BT-Vendor hf callback structure. */
+typedef struct {
+    /** set to sizeof(BtVendorhfCallbacks) */
+    size_t      size;
+    bt_swb_update_callback  swb_codec_cb;
+} btvendor_hf_callbacks_t;
+
+
+/** Represents the standard BT-Vendor hf interface.
+ */
+typedef struct {
+    /** set to sizeof(BtVendorHfInterface) */
+    size_t  size;
+
+    /**
+     * Register the BtVendorhf callbacks
+     */
+    bt_status_t (*init)( btvendor_hf_callbacks_t* callbacks );
+
+    /** Closes the interface. */
+    void  (*cleanup)( void );
+
+    int   (*enable_swb) (bool enable);
+} btvendor_hf_interface_t;
+
+__END_DECLS
+#endif /* ANDROID_INCLUDE_BT_VENDOR_H */
+